mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-23 14:40:36 +01:00
Merge remote-tracking branch 'btcpayserver/master' into feature/crowdfund
This commit is contained in:
commit
8e8615dab8
33 changed files with 558 additions and 167 deletions
|
@ -7,23 +7,16 @@ jobs:
|
||||||
- checkout
|
- checkout
|
||||||
|
|
||||||
test:
|
test:
|
||||||
machine: true
|
machine:
|
||||||
|
docker_layer_caching: true
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
lsb_release -a
|
|
||||||
wget -q https://packages.microsoft.com/config/ubuntu/14.04/packages-microsoft-prod.deb
|
|
||||||
sudo dpkg -i packages-microsoft-prod.deb
|
|
||||||
sudo apt-get install apt-transport-https
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install dotnet-sdk-2.1
|
|
||||||
dotnet --info
|
|
||||||
dotnet build /p:TreatWarningsAsErrors=true
|
|
||||||
cd BTCPayServer.Tests
|
cd BTCPayServer.Tests
|
||||||
dotnet test --filter Fast=Fast
|
docker-compose down --v
|
||||||
docker-compose up -d dev
|
docker-compose build
|
||||||
dotnet test --filter Integration=Integration
|
docker-compose run tests
|
||||||
|
|
||||||
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
|
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
|
||||||
publish_docker_linuxamd64:
|
publish_docker_linuxamd64:
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
FROM microsoft/dotnet:2.1.403-sdk-alpine3.7
|
FROM microsoft/dotnet:2.1.500-sdk-alpine3.7 AS builder
|
||||||
WORKDIR /app
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
|
||||||
# caches restore result by copying csproj file separately
|
RUN apk add --no-cache icu-libs
|
||||||
COPY BTCPayServer.Tests/BTCPayServer.Tests.csproj BTCPayServer.Tests/BTCPayServer.Tests.csproj
|
ENV LC_ALL en_US.UTF-8
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
|
||||||
|
# This should be removed soon https://github.com/dotnet/corefx/issues/30003
|
||||||
|
RUN apk add --no-cache curl
|
||||||
|
|
||||||
|
WORKDIR /source
|
||||||
COPY BTCPayServer/BTCPayServer.csproj BTCPayServer/BTCPayServer.csproj
|
COPY BTCPayServer/BTCPayServer.csproj BTCPayServer/BTCPayServer.csproj
|
||||||
|
COPY BTCPayServer.Tests/BTCPayServer.Tests.csproj BTCPayServer.Tests/BTCPayServer.Tests.csproj
|
||||||
WORKDIR /app/BTCPayServer.Tests
|
RUN dotnet restore BTCPayServer.Tests/BTCPayServer.Tests.csproj
|
||||||
RUN dotnet restore
|
COPY . .
|
||||||
# copies the rest of your code
|
RUN dotnet build
|
||||||
COPY . ../.
|
WORKDIR /source/BTCPayServer.Tests
|
||||||
|
ENTRYPOINT ["./docker-entrypoint.sh"]
|
||||||
ENTRYPOINT ["dotnet", "test"]
|
|
||||||
|
|
|
@ -345,15 +345,17 @@ namespace BTCPayServer.Tests
|
||||||
(0.01m, "$0.01 (USD)", "USD"),
|
(0.01m, "$0.01 (USD)", "USD"),
|
||||||
(0.1m, "$0.10 (USD)", "USD"),
|
(0.1m, "$0.10 (USD)", "USD"),
|
||||||
(0.1m, "0,10 € (EUR)", "EUR"),
|
(0.1m, "0,10 € (EUR)", "EUR"),
|
||||||
|
(1000m, "¥1,000 (JPY)", "JPY"),
|
||||||
(1000.0001m, "₹ 1,000.00 (INR)", "INR")
|
(1000.0001m, "₹ 1,000.00 (INR)", "INR")
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
var actual = new CurrencyNameTable().DisplayFormatCurrency(test.Item1, test.Item3);
|
var actual = new CurrencyNameTable().DisplayFormatCurrency(test.Item1, test.Item3);
|
||||||
|
actual = actual.Replace("¥", "¥"); // Hack so JPY test pass on linux as well
|
||||||
Assert.Equal(test.Item2, actual);
|
Assert.Equal(test.Item2, actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact(Timeout = 60 * 1000)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanSetLightningServer()
|
public async Task CanSetLightningServer()
|
||||||
{
|
{
|
||||||
|
@ -405,7 +407,7 @@ namespace BTCPayServer.Tests
|
||||||
await ProcessLightningPayment(LightningConnectionType.Charge);
|
await ProcessLightningPayment(LightningConnectionType.Charge);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact(Timeout = 60 * 1000)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanSendLightningPaymentLnd()
|
public async Task CanSendLightningPaymentLnd()
|
||||||
{
|
{
|
||||||
|
@ -1360,7 +1362,7 @@ namespace BTCPayServer.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact(Timeout = 60 * 1000)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanSetPaymentMethodLimits()
|
public async Task CanSetPaymentMethodLimits()
|
||||||
{
|
{
|
||||||
|
@ -1470,7 +1472,7 @@ donation:
|
||||||
Assert.Equal("CAD", donationInvoice.Currency);
|
Assert.Equal("CAD", donationInvoice.Currency);
|
||||||
Assert.Equal("donation", donationInvoice.ItemDesc);
|
Assert.Equal("donation", donationInvoice.ItemDesc);
|
||||||
|
|
||||||
foreach(var test in new[]
|
foreach (var test in new[]
|
||||||
{
|
{
|
||||||
(Code: "EUR", ExpectedSymbol: "€", ExpectedDecimalSeparator: ",", ExpectedDivisibility: 2, ExpectedThousandSeparator: "\xa0", ExpectedPrefixed: false, ExpectedSymbolSpace: true),
|
(Code: "EUR", ExpectedSymbol: "€", ExpectedDecimalSeparator: ",", ExpectedDivisibility: 2, ExpectedThousandSeparator: "\xa0", ExpectedPrefixed: false, ExpectedSymbolSpace: true),
|
||||||
(Code: "INR", ExpectedSymbol: "₹", ExpectedDecimalSeparator: ".", ExpectedDivisibility: 2, ExpectedThousandSeparator: ",", ExpectedPrefixed: true, ExpectedSymbolSpace: true),
|
(Code: "INR", ExpectedSymbol: "₹", ExpectedDecimalSeparator: ".", ExpectedDivisibility: 2, ExpectedThousandSeparator: ",", ExpectedPrefixed: true, ExpectedSymbolSpace: true),
|
||||||
|
@ -1499,8 +1501,8 @@ donation:
|
||||||
publicApps = user.GetController<AppsPublicController>();
|
publicApps = user.GetController<AppsPublicController>();
|
||||||
vmview = Assert.IsType<ViewPointOfSaleViewModel>(Assert.IsType<ViewResult>(publicApps.ViewPointOfSale(appId).Result).Model);
|
vmview = Assert.IsType<ViewPointOfSaleViewModel>(Assert.IsType<ViewResult>(publicApps.ViewPointOfSale(appId).Result).Model);
|
||||||
Assert.Equal(test.Code, vmview.CurrencyCode);
|
Assert.Equal(test.Code, vmview.CurrencyCode);
|
||||||
Assert.Equal(test.ExpectedSymbol, vmview.CurrencySymbol);
|
Assert.Equal(test.ExpectedSymbol, vmview.CurrencySymbol.Replace("¥", "¥")); // Hack so JPY test pass on linux as well);
|
||||||
Assert.Equal(test.ExpectedSymbol, vmview.CurrencyInfo.CurrencySymbol);
|
Assert.Equal(test.ExpectedSymbol, vmview.CurrencyInfo.CurrencySymbol.Replace("¥", "¥")); // Hack so JPY test pass on linux as well);
|
||||||
Assert.Equal(test.ExpectedDecimalSeparator, vmview.CurrencyInfo.DecimalSeparator);
|
Assert.Equal(test.ExpectedDecimalSeparator, vmview.CurrencyInfo.DecimalSeparator);
|
||||||
Assert.Equal(test.ExpectedThousandSeparator, vmview.CurrencyInfo.ThousandSeparator);
|
Assert.Equal(test.ExpectedThousandSeparator, vmview.CurrencyInfo.ThousandSeparator);
|
||||||
Assert.Equal(test.ExpectedPrefixed, vmview.CurrencyInfo.Prefixed);
|
Assert.Equal(test.ExpectedPrefixed, vmview.CurrencyInfo.Prefixed);
|
||||||
|
@ -1620,10 +1622,9 @@ donation:
|
||||||
var jsonResultPaid = user.GetController<InvoiceController>().Export("json").GetAwaiter().GetResult();
|
var jsonResultPaid = user.GetController<InvoiceController>().Export("json").GetAwaiter().GetResult();
|
||||||
var paidresult = Assert.IsType<ContentResult>(jsonResultPaid);
|
var paidresult = Assert.IsType<ContentResult>(jsonResultPaid);
|
||||||
Assert.Equal("application/json", paidresult.ContentType);
|
Assert.Equal("application/json", paidresult.ContentType);
|
||||||
Assert.Contains("\"ItemDesc\": \"Some \\\", description\"", paidresult.Content);
|
Assert.Contains("\"InvoiceItemDesc\": \"Some \\\", description\"", paidresult.Content);
|
||||||
Assert.Contains("\"FiatPrice\": 500.0", paidresult.Content);
|
Assert.Contains("\"InvoicePrice\": 500.0", paidresult.Content);
|
||||||
Assert.Contains("\"ConversionRate\": 5000.0", paidresult.Content);
|
Assert.Contains("\"ConversionRate\": 5000.0", paidresult.Content);
|
||||||
Assert.Contains("\"PaymentDue\": \"0.10020000 BTC\"", paidresult.Content);
|
|
||||||
Assert.Contains($"\"InvoiceId\": \"{invoice.Id}\",", paidresult.Content);
|
Assert.Contains($"\"InvoiceId\": \"{invoice.Id}\",", paidresult.Content);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1688,14 +1689,9 @@ donation:
|
||||||
var paidresult = Assert.IsType<ContentResult>(exportResultPaid);
|
var paidresult = Assert.IsType<ContentResult>(exportResultPaid);
|
||||||
Assert.Equal("application/csv", paidresult.ContentType);
|
Assert.Equal("application/csv", paidresult.ContentType);
|
||||||
Assert.Contains($",\"orderId\",\"{invoice.Id}\",", paidresult.Content);
|
Assert.Contains($",\"orderId\",\"{invoice.Id}\",", paidresult.Content);
|
||||||
Assert.Contains($",\"OnChain\",\"0.10020000 BTC\",\"0.10009990 BTC\",\"0.00000000 BTC\",\"5000.0\",\"500.0\"", paidresult.Content);
|
Assert.Contains($",\"OnChain\",\"0.1000999\",\"BTC\",\"5000.0\",\"500.0\"", paidresult.Content);
|
||||||
Assert.Contains($",\"USD\",\"\",\"Some ``, description\",\"new\"", paidresult.Content);
|
Assert.Contains($",\"USD\",\"\",\"Some ``, description\",\"new (paidPartial)\"", paidresult.Content);
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
ReceivedDate,StoreId,OrderId,InvoiceId,CreatedDate,ExpirationDate,MonitoringDate,PaymentId,CryptoCode,Destination,PaymentType,PaymentDue,PaymentPaid,PaymentOverpaid,ConversionRate,FiatPrice,FiatCurrency,ItemCode,ItemDesc,Status
|
|
||||||
"11/30/2018 10:28:42 AM","7AagXzWdWhLLR3Zar25YLiw2uHAJDzVT4oXGKC9bBCis","orderId","GxtJsWbgxxAXXoCurqyeK6","11/30/2018 10:28:40 AM","11/30/2018 10:43:40 AM","11/30/2018 11:43:40 AM","ec0341537f565d213bc64caa352fbbf9e0deb31cab1f91bccf89db0dd1604457-0","BTC","mqWghCp9RVw8fNgQMLjawyKStxpGfWBk1L","OnChain","0.10020000 BTC","0.10009990 BTC","0.00000000 BTC","5000.0","500.0","USD","","Some ``, description","new"
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,10 @@ services:
|
||||||
TESTS_MYSQL: User ID=root;Host=mysql;Port=3306;Database=btcpayserver
|
TESTS_MYSQL: User ID=root;Host=mysql;Port=3306;Database=btcpayserver
|
||||||
TESTS_PORT: 80
|
TESTS_PORT: 80
|
||||||
TESTS_HOSTNAME: tests
|
TESTS_HOSTNAME: tests
|
||||||
TEST_MERCHANTLIGHTNINGD: "type=clightning;server=/etc/merchant_lightningd_datadir/lightning-rpc"
|
TEST_MERCHANTLIGHTNINGD: "type=clightning;server=unix://etc/merchant_lightningd_datadir/lightning-rpc"
|
||||||
TEST_CUSTOMERLIGHTNINGD: "type=clightning;server=/etc/customer_lightningd_datadir/lightning-rpc"
|
TEST_CUSTOMERLIGHTNINGD: "type=clightning;server=unix://etc/customer_lightningd_datadir/lightning-rpc"
|
||||||
TEST_MERCHANTCHARGE: "type=charge;server=https://lightning-charged:9112/;api-token=foiewnccewuify;allowinsecure=true"
|
TEST_MERCHANTCHARGE: "type=charge;server=http://lightning-charged:9112/;api-token=foiewnccewuify"
|
||||||
TEST_MERCHANTLND: "type=lnd-rest;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true"
|
TEST_MERCHANTLND: "https://lnd:lnd@merchant_lnd:8080/"
|
||||||
TESTS_INCONTAINER: "true"
|
TESTS_INCONTAINER: "true"
|
||||||
expose:
|
expose:
|
||||||
- "80"
|
- "80"
|
||||||
|
@ -36,7 +36,7 @@ services:
|
||||||
|
|
||||||
# The dev container is not actually used, it is just handy to run `docker-compose up dev` to start all services
|
# The dev container is not actually used, it is just handy to run `docker-compose up dev` to start all services
|
||||||
dev:
|
dev:
|
||||||
image: nicolasdorier/docker-bitcoin:0.17.0
|
image: btcpayserver/bitcoin:0.17.0
|
||||||
environment:
|
environment:
|
||||||
BITCOIN_NETWORK: regtest
|
BITCOIN_NETWORK: regtest
|
||||||
BITCOIN_EXTRA_ARGS: |
|
BITCOIN_EXTRA_ARGS: |
|
||||||
|
@ -53,7 +53,7 @@ services:
|
||||||
- merchant_lnd
|
- merchant_lnd
|
||||||
|
|
||||||
devlnd:
|
devlnd:
|
||||||
image: nicolasdorier/docker-bitcoin:0.17.0
|
image: btcpayserver/bitcoin:0.17.0
|
||||||
environment:
|
environment:
|
||||||
BITCOIN_NETWORK: regtest
|
BITCOIN_NETWORK: regtest
|
||||||
BITCOIN_EXTRA_ARGS: |
|
BITCOIN_EXTRA_ARGS: |
|
||||||
|
@ -93,12 +93,13 @@ services:
|
||||||
- bitcoind
|
- bitcoind
|
||||||
- litecoind
|
- litecoind
|
||||||
|
|
||||||
|
|
||||||
bitcoind:
|
bitcoind:
|
||||||
image: nicolasdorier/docker-bitcoin:0.17.0
|
restart: unless-stopped
|
||||||
|
image: btcpayserver/bitcoin:0.17.0
|
||||||
environment:
|
environment:
|
||||||
BITCOIN_NETWORK: regtest
|
BITCOIN_NETWORK: regtest
|
||||||
BITCOIN_EXTRA_ARGS: |
|
BITCOIN_EXTRA_ARGS: |-
|
||||||
deprecatedrpc=signrawtransaction
|
|
||||||
rpcuser=ceiwHEbqWI83
|
rpcuser=ceiwHEbqWI83
|
||||||
rpcpassword=DwubwWsoo3
|
rpcpassword=DwubwWsoo3
|
||||||
rpcport=43782
|
rpcport=43782
|
||||||
|
@ -106,9 +107,9 @@ services:
|
||||||
whitelist=0.0.0.0/0
|
whitelist=0.0.0.0/0
|
||||||
zmqpubrawblock=tcp://0.0.0.0:28332
|
zmqpubrawblock=tcp://0.0.0.0:28332
|
||||||
zmqpubrawtx=tcp://0.0.0.0:28333
|
zmqpubrawtx=tcp://0.0.0.0:28333
|
||||||
|
deprecatedrpc=signrawtransaction
|
||||||
ports:
|
ports:
|
||||||
- "43782:43782"
|
- "43782:43782"
|
||||||
- "28332:28332"
|
|
||||||
expose:
|
expose:
|
||||||
- "43782" # RPC
|
- "43782" # RPC
|
||||||
- "39388" # P2P
|
- "39388" # P2P
|
||||||
|
@ -118,7 +119,7 @@ services:
|
||||||
- "bitcoin_datadir:/data"
|
- "bitcoin_datadir:/data"
|
||||||
|
|
||||||
customer_lightningd:
|
customer_lightningd:
|
||||||
image: nicolasdorier/clightning:v0.6.2-3-dev
|
image: btcpayserver/lightning:v0.6.2-dev
|
||||||
stop_signal: SIGKILL
|
stop_signal: SIGKILL
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
|
@ -144,7 +145,7 @@ services:
|
||||||
- bitcoind
|
- bitcoind
|
||||||
|
|
||||||
lightning-charged:
|
lightning-charged:
|
||||||
image: shesek/lightning-charge:0.4.3
|
image: shesek/lightning-charge:0.4.6-standalone
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
NETWORK: regtest
|
NETWORK: regtest
|
||||||
|
@ -164,7 +165,7 @@ services:
|
||||||
- merchant_lightningd
|
- merchant_lightningd
|
||||||
|
|
||||||
merchant_lightningd:
|
merchant_lightningd:
|
||||||
image: nicolasdorier/clightning:v0.6.2-3-dev
|
image: btcpayserver/lightning:v0.6.2-dev
|
||||||
stop_signal: SIGKILL
|
stop_signal: SIGKILL
|
||||||
environment:
|
environment:
|
||||||
EXPOSE_TCP: "true"
|
EXPOSE_TCP: "true"
|
||||||
|
@ -188,13 +189,13 @@ services:
|
||||||
- bitcoind
|
- bitcoind
|
||||||
|
|
||||||
litecoind:
|
litecoind:
|
||||||
image: nicolasdorier/docker-litecoin:0.15.1
|
restart: unless-stopped
|
||||||
|
image: nicolasdorier/docker-litecoin:0.16.3
|
||||||
environment:
|
environment:
|
||||||
BITCOIN_EXTRA_ARGS: |
|
BITCOIN_EXTRA_ARGS: |-
|
||||||
rpcuser=ceiwHEbqWI83
|
rpcuser=ceiwHEbqWI83
|
||||||
rpcpassword=DwubwWsoo3
|
rpcpassword=DwubwWsoo3
|
||||||
regtest=1
|
regtest=1
|
||||||
server=1
|
|
||||||
rpcport=43782
|
rpcport=43782
|
||||||
port=39388
|
port=39388
|
||||||
whitelist=0.0.0.0/0
|
whitelist=0.0.0.0/0
|
||||||
|
@ -221,13 +222,16 @@ services:
|
||||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||||
|
|
||||||
merchant_lnd:
|
merchant_lnd:
|
||||||
image: btcpayserver/lnd:0.5-beta-2
|
image: btcpayserver/lnd:v0.5.1-beta
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
LND_CHAIN: "btc"
|
LND_CHAIN: "btc"
|
||||||
LND_ENVIRONMENT: "regtest"
|
LND_ENVIRONMENT: "regtest"
|
||||||
|
LND_EXPLORERURL: "http://nbxplorer:32838/"
|
||||||
LND_EXTRA_ARGS: |
|
LND_EXTRA_ARGS: |
|
||||||
restlisten=0.0.0.0:8080
|
restlisten=0.0.0.0:8080
|
||||||
|
rpclisten=127.0.0.1:10008
|
||||||
|
rpclisten=0.0.0.0:10009
|
||||||
bitcoin.node=bitcoind
|
bitcoin.node=bitcoind
|
||||||
bitcoind.rpchost=bitcoind:43782
|
bitcoind.rpchost=bitcoind:43782
|
||||||
bitcoind.zmqpubrawblock=tcp://bitcoind:28332
|
bitcoind.zmqpubrawblock=tcp://bitcoind:28332
|
||||||
|
@ -248,13 +252,16 @@ services:
|
||||||
- bitcoind
|
- bitcoind
|
||||||
|
|
||||||
customer_lnd:
|
customer_lnd:
|
||||||
image: btcpayserver/lnd:0.5-beta-2
|
image: btcpayserver/lnd:v0.5.1-beta
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
LND_CHAIN: "btc"
|
LND_CHAIN: "btc"
|
||||||
LND_ENVIRONMENT: "regtest"
|
LND_ENVIRONMENT: "regtest"
|
||||||
|
LND_EXPLORERURL: "http://nbxplorer:32838/"
|
||||||
LND_EXTRA_ARGS: |
|
LND_EXTRA_ARGS: |
|
||||||
restlisten=0.0.0.0:8080
|
restlisten=0.0.0.0:8080
|
||||||
|
rpclisten=127.0.0.1:10008
|
||||||
|
rpclisten=0.0.0.0:10009
|
||||||
bitcoin.node=bitcoind
|
bitcoin.node=bitcoind
|
||||||
bitcoind.rpchost=bitcoind:43782
|
bitcoind.rpchost=bitcoind:43782
|
||||||
bitcoind.zmqpubrawblock=tcp://bitcoind:28332
|
bitcoind.zmqpubrawblock=tcp://bitcoind:28332
|
||||||
|
|
5
BTCPayServer.Tests/docker-entrypoint.sh
Executable file
5
BTCPayServer.Tests/docker-entrypoint.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
dotnet test --filter Fast=Fast --no-build
|
||||||
|
dotnet test --filter Integration=Integration --no-build -v n
|
|
@ -1,3 +1,5 @@
|
||||||
{
|
{
|
||||||
"parallelizeTestCollections": false
|
"parallelizeTestCollections": false,
|
||||||
|
"longRunningTestSeconds": 60,
|
||||||
|
"diagnosticMessages": true
|
||||||
}
|
}
|
|
@ -26,7 +26,7 @@ namespace BTCPayServer
|
||||||
"GRS_BTC = bittrex(GRS_BTC)"
|
"GRS_BTC = bittrex(GRS_BTC)"
|
||||||
},
|
},
|
||||||
CryptoImagePath = "imlegacy/groestlcoin.png",
|
CryptoImagePath = "imlegacy/groestlcoin.png",
|
||||||
LightningImagePath = "imlegacy/groestlcoin-lightning.png",
|
LightningImagePath = "imlegacy/groestlcoin-lightning.svg",
|
||||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("17'") : new KeyPath("1'")
|
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("17'") : new KeyPath("1'")
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<Version>1.0.3.31</Version>
|
<Version>1.0.3.34</Version>
|
||||||
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
|
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
<EmbeddedResource Include="Currencies.txt" />
|
<EmbeddedResource Include="Currencies.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.1.0.3" />
|
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.1.0.4" />
|
||||||
<PackageReference Include="BuildBundlerMinifier" Version="2.7.385" />
|
<PackageReference Include="BuildBundlerMinifier" Version="2.7.385" />
|
||||||
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.5.3" />
|
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.5.3" />
|
||||||
<PackageReference Include="Hangfire" Version="1.6.20" />
|
<PackageReference Include="Hangfire" Version="1.6.20" />
|
||||||
|
@ -136,6 +136,9 @@
|
||||||
<Content Update="Views\Home\BitpayTranslator.cshtml">
|
<Content Update="Views\Home\BitpayTranslator.cshtml">
|
||||||
<Pack>$(IncludeRazorContentInPack)</Pack>
|
<Pack>$(IncludeRazorContentInPack)</Pack>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Update="Views\Server\LightningChargeServices.cshtml">
|
||||||
|
<Pack>$(IncludeRazorContentInPack)</Pack>
|
||||||
|
</Content>
|
||||||
<Content Update="Views\Server\SparkServices.cshtml">
|
<Content Update="Views\Server\SparkServices.cshtml">
|
||||||
<Pack>$(IncludeRazorContentInPack)</Pack>
|
<Pack>$(IncludeRazorContentInPack)</Pack>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace BTCPayServer.Configuration
|
||||||
externalLnd<ExternalLndRest>($"{net.CryptoCode}.external.lnd.rest", "lnd-rest");
|
externalLnd<ExternalLndRest>($"{net.CryptoCode}.external.lnd.rest", "lnd-rest");
|
||||||
|
|
||||||
var spark = conf.GetOrDefault<string>($"{net.CryptoCode}.external.spark", string.Empty);
|
var spark = conf.GetOrDefault<string>($"{net.CryptoCode}.external.spark", string.Empty);
|
||||||
if(spark.Length != 0)
|
if (spark.Length != 0)
|
||||||
{
|
{
|
||||||
if (!SparkConnectionString.TryParse(spark, out var connectionString))
|
if (!SparkConnectionString.TryParse(spark, out var connectionString))
|
||||||
{
|
{
|
||||||
|
@ -148,14 +148,30 @@ namespace BTCPayServer.Configuration
|
||||||
}
|
}
|
||||||
ExternalServicesByCryptoCode.Add(net.CryptoCode, new ExternalSpark(connectionString));
|
ExternalServicesByCryptoCode.Add(net.CryptoCode, new ExternalSpark(connectionString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var charge = conf.GetOrDefault<string>($"{net.CryptoCode}.external.charge", string.Empty);
|
||||||
|
if (charge.Length != 0)
|
||||||
|
{
|
||||||
|
if (!LightningConnectionString.TryParse(charge, false, out var chargeConnectionString, out var chargeError))
|
||||||
|
LightningConnectionString.TryParse("type=charge;" + charge, false, out chargeConnectionString, out chargeError);
|
||||||
|
|
||||||
|
if(chargeConnectionString == null || chargeConnectionString.ConnectionType != LightningConnectionType.Charge)
|
||||||
|
{
|
||||||
|
throw new ConfigException($"Invalid setting {net.CryptoCode}.external.charge, " + Environment.NewLine +
|
||||||
|
$"lightning charge server: 'type=charge;server=https://charge.example.com;api-token=2abdf302...'" + Environment.NewLine +
|
||||||
|
$"lightning charge server: 'type=charge;server=https://charge.example.com;cookiefilepath=/root/.charge/.cookie'" + Environment.NewLine +
|
||||||
|
chargeError ?? string.Empty);
|
||||||
|
}
|
||||||
|
ExternalServicesByCryptoCode.Add(net.CryptoCode, new ExternalCharge(chargeConnectionString));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logs.Configuration.LogInformation("Supported chains: " + String.Join(',', supportedChains.ToArray()));
|
Logs.Configuration.LogInformation("Supported chains: " + String.Join(',', supportedChains.ToArray()));
|
||||||
|
|
||||||
var services = conf.GetOrDefault<string>("externalservices", null);
|
var services = conf.GetOrDefault<string>("externalservices", null);
|
||||||
if(services != null)
|
if (services != null)
|
||||||
{
|
{
|
||||||
foreach(var service in services.Split(new[] { ';', ',' })
|
foreach (var service in services.Split(new[] { ';', ',' })
|
||||||
.Select(p => p.Split(':'))
|
.Select(p => p.Split(':'))
|
||||||
.Where(p => p.Length == 2)
|
.Where(p => p.Length == 2)
|
||||||
.Select(p => (Name: p[0], Link: p[1])))
|
.Select(p => (Name: p[0], Link: p[1])))
|
||||||
|
|
|
@ -50,7 +50,8 @@ namespace BTCPayServer.Configuration
|
||||||
app.Option($"--{crypto}explorercookiefile", $"Path to the cookie file (default: {network.NBXplorerNetwork.DefaultSettings.DefaultCookieFile})", CommandOptionType.SingleValue);
|
app.Option($"--{crypto}explorercookiefile", $"Path to the cookie file (default: {network.NBXplorerNetwork.DefaultSettings.DefaultCookieFile})", CommandOptionType.SingleValue);
|
||||||
app.Option($"--{crypto}lightning", $"Easy configuration of lightning for the server administrator: Must be a UNIX socket of c-lightning (lightning-rpc) or URL to a charge server (default: empty)", CommandOptionType.SingleValue);
|
app.Option($"--{crypto}lightning", $"Easy configuration of lightning for the server administrator: Must be a UNIX socket of c-lightning (lightning-rpc) or URL to a charge server (default: empty)", CommandOptionType.SingleValue);
|
||||||
app.Option($"--{crypto}externallndgrpc", $"The LND gRPC configuration BTCPay will expose to easily connect to the internal lnd wallet from Zap wallet (default: empty)", CommandOptionType.SingleValue);
|
app.Option($"--{crypto}externallndgrpc", $"The LND gRPC configuration BTCPay will expose to easily connect to the internal lnd wallet from Zap wallet (default: empty)", CommandOptionType.SingleValue);
|
||||||
app.Option($"--{crypto}externalspark", $"The connection string to spark server (default: empty)", CommandOptionType.SingleValue);
|
app.Option($"--{crypto}externalspark", $"Show spark information in Server settings / Server. The connection string to spark server (default: empty)", CommandOptionType.SingleValue);
|
||||||
|
app.Option($"--{crypto}externalcharge", $"Show lightning charge information in Server settings/Server. The connection string to charge server (default: empty)", CommandOptionType.SingleValue);
|
||||||
}
|
}
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
19
BTCPayServer/Configuration/External/ExternalCharge.cs
vendored
Normal file
19
BTCPayServer/Configuration/External/ExternalCharge.cs
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Lightning;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Configuration.External
|
||||||
|
{
|
||||||
|
public class ExternalCharge : ExternalService
|
||||||
|
{
|
||||||
|
public ExternalCharge(LightningConnectionString connectionString)
|
||||||
|
{
|
||||||
|
if (connectionString == null)
|
||||||
|
throw new ArgumentNullException(nameof(connectionString));
|
||||||
|
ConnectionString = connectionString;
|
||||||
|
}
|
||||||
|
public LightningConnectionString ConnectionString { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ namespace BTCPayServer.Configuration
|
||||||
resultTemp.Server = new Uri(kv[1], UriKind.Absolute);
|
resultTemp.Server = new Uri(kv[1], UriKind.Absolute);
|
||||||
break;
|
break;
|
||||||
case "cookiefile":
|
case "cookiefile":
|
||||||
|
case "cookiefilepath":
|
||||||
if (resultTemp.CookeFile != null)
|
if (resultTemp.CookeFile != null)
|
||||||
return false;
|
return false;
|
||||||
resultTemp.CookeFile = kv[1];
|
resultTemp.CookeFile = kv[1];
|
||||||
|
|
|
@ -103,7 +103,7 @@ namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
var m = new InvoiceDetailsModel.Payment();
|
var m = new InvoiceDetailsModel.Payment();
|
||||||
m.Crypto = payment.GetPaymentMethodId().CryptoCode;
|
m.Crypto = payment.GetPaymentMethodId().CryptoCode;
|
||||||
m.DepositAddress = onChainPaymentData.Output.ScriptPubKey.GetDestinationAddress(paymentNetwork.NBitcoinNetwork);
|
m.DepositAddress = onChainPaymentData.GetDestination(paymentNetwork);
|
||||||
|
|
||||||
int confirmationCount = 0;
|
int confirmationCount = 0;
|
||||||
if ((onChainPaymentData.ConfirmationCount < paymentNetwork.MaxTrackedConfirmation && payment.Accounted)
|
if ((onChainPaymentData.ConfirmationCount < paymentNetwork.MaxTrackedConfirmation && payment.Accounted)
|
||||||
|
@ -484,7 +484,7 @@ namespace BTCPayServer.Controllers
|
||||||
[BitpayAPIConstraint(false)]
|
[BitpayAPIConstraint(false)]
|
||||||
public async Task<IActionResult> Export(string format, string searchTerm = null)
|
public async Task<IActionResult> Export(string format, string searchTerm = null)
|
||||||
{
|
{
|
||||||
var model = new InvoiceExport();
|
var model = new InvoiceExport(_NetworkProvider);
|
||||||
|
|
||||||
var invoices = await ListInvoicesProcess(searchTerm, 0, int.MaxValue);
|
var invoices = await ListInvoicesProcess(searchTerm, 0, int.MaxValue);
|
||||||
var res = model.Process(invoices, format);
|
var res = model.Process(invoices, format);
|
||||||
|
|
57
BTCPayServer/Controllers/Macaroons.cs
Normal file
57
BTCPayServer/Controllers/Macaroons.cs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Controllers
|
||||||
|
{
|
||||||
|
public class Macaroons
|
||||||
|
{
|
||||||
|
public class Macaroon
|
||||||
|
{
|
||||||
|
public Macaroon(byte[] bytes)
|
||||||
|
{
|
||||||
|
Bytes = bytes;
|
||||||
|
Hex = NBitcoin.DataEncoders.Encoders.Hex.EncodeData(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Hex { get; set; }
|
||||||
|
public byte[] Bytes { get; set; }
|
||||||
|
}
|
||||||
|
public static async Task<Macaroons> GetFromDirectoryAsync(string directoryPath)
|
||||||
|
{
|
||||||
|
if (directoryPath == null)
|
||||||
|
throw new ArgumentNullException(nameof(directoryPath));
|
||||||
|
Macaroons macaroons = new Macaroons();
|
||||||
|
if (!Directory.Exists(directoryPath))
|
||||||
|
return macaroons;
|
||||||
|
foreach(var file in Directory.GetFiles(directoryPath, "*.macaroon"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (Path.GetFileName(file))
|
||||||
|
{
|
||||||
|
case "admin.macaroon":
|
||||||
|
macaroons.AdminMacaroon = new Macaroon(await File.ReadAllBytesAsync(file));
|
||||||
|
break;
|
||||||
|
case "readonly.macaroon":
|
||||||
|
macaroons.ReadonlyMacaroon = new Macaroon(await File.ReadAllBytesAsync(file));
|
||||||
|
break;
|
||||||
|
case "invoice.macaroon":
|
||||||
|
macaroons.InvoiceMacaroon = new Macaroon(await File.ReadAllBytesAsync(file));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
return macaroons;
|
||||||
|
}
|
||||||
|
public Macaroon ReadonlyMacaroon { get; set; }
|
||||||
|
|
||||||
|
public Macaroon InvoiceMacaroon { get; set; }
|
||||||
|
public Macaroon AdminMacaroon { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -449,6 +449,16 @@ namespace BTCPayServer.Controllers
|
||||||
Index = i++,
|
Index = i++,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
foreach (var chargeService in _Options.ExternalServicesByCryptoCode.GetServices<ExternalCharge>(cryptoCode))
|
||||||
|
{
|
||||||
|
result.LNDServices.Add(new ServicesViewModel.LNDServiceViewModel()
|
||||||
|
{
|
||||||
|
Crypto = cryptoCode,
|
||||||
|
Type = "Lightning charge server",
|
||||||
|
Action = nameof(LightningChargeServices),
|
||||||
|
Index = i++,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach(var externalService in _Options.ExternalServices)
|
foreach(var externalService in _Options.ExternalServices)
|
||||||
{
|
{
|
||||||
|
@ -469,6 +479,45 @@ namespace BTCPayServer.Controllers
|
||||||
return View(result);
|
return View(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("server/services/lightning-charge/{cryptoCode}/{index}")]
|
||||||
|
public async Task<IActionResult> LightningChargeServices(string cryptoCode, int index, bool showQR = false)
|
||||||
|
{
|
||||||
|
if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
|
||||||
|
{
|
||||||
|
StatusMessage = $"Error: {cryptoCode} is not fully synched";
|
||||||
|
return RedirectToAction(nameof(Services));
|
||||||
|
}
|
||||||
|
var lightningCharge = _Options.ExternalServicesByCryptoCode.GetServices<ExternalCharge>(cryptoCode).Select(c => c.ConnectionString).FirstOrDefault();
|
||||||
|
if (lightningCharge == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChargeServiceViewModel vm = new ChargeServiceViewModel();
|
||||||
|
vm.Uri = lightningCharge.ToUri(false).AbsoluteUri;
|
||||||
|
vm.APIToken = lightningCharge.Password;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(vm.APIToken) && lightningCharge.CookieFilePath != null)
|
||||||
|
{
|
||||||
|
if (lightningCharge.CookieFilePath != "fake")
|
||||||
|
vm.APIToken = await System.IO.File.ReadAllTextAsync(lightningCharge.CookieFilePath);
|
||||||
|
else
|
||||||
|
vm.APIToken = "fake";
|
||||||
|
}
|
||||||
|
var builder = new UriBuilder(lightningCharge.ToUri(false));
|
||||||
|
builder.UserName = "api-token";
|
||||||
|
builder.Password = vm.APIToken;
|
||||||
|
vm.AuthenticatedUri = builder.ToString();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
StatusMessage = $"Error: {ex.Message}";
|
||||||
|
return RedirectToAction(nameof(Services));
|
||||||
|
}
|
||||||
|
return View(vm);
|
||||||
|
}
|
||||||
|
|
||||||
[Route("server/services/spark/{cryptoCode}/{index}")]
|
[Route("server/services/spark/{cryptoCode}/{index}")]
|
||||||
public async Task<IActionResult> SparkServices(string cryptoCode, int index, bool showQR = false)
|
public async Task<IActionResult> SparkServices(string cryptoCode, int index, bool showQR = false)
|
||||||
{
|
{
|
||||||
|
@ -477,7 +526,7 @@ namespace BTCPayServer.Controllers
|
||||||
StatusMessage = $"Error: {cryptoCode} is not fully synched";
|
StatusMessage = $"Error: {cryptoCode} is not fully synched";
|
||||||
return RedirectToAction(nameof(Services));
|
return RedirectToAction(nameof(Services));
|
||||||
}
|
}
|
||||||
var spark = _Options.ExternalServicesByCryptoCode.GetServices<ExternalSpark>(cryptoCode).Skip(index).Select(c => c.ConnectionString).FirstOrDefault();
|
var spark = _Options.ExternalServicesByCryptoCode.GetServices<ExternalSpark>(cryptoCode).Select(c => c.ConnectionString).FirstOrDefault();
|
||||||
if(spark == null)
|
if(spark == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
@ -504,7 +553,7 @@ namespace BTCPayServer.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("server/services/lnd/{cryptoCode}/{index}")]
|
[Route("server/services/lnd/{cryptoCode}/{index}")]
|
||||||
public IActionResult LndServices(string cryptoCode, int index, uint? nonce)
|
public async Task<IActionResult> LndServices(string cryptoCode, int index, uint? nonce)
|
||||||
{
|
{
|
||||||
if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
|
if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
|
||||||
{
|
{
|
||||||
|
@ -520,6 +569,7 @@ namespace BTCPayServer.Controllers
|
||||||
model.Host = $"{external.BaseUri.DnsSafeHost}:{external.BaseUri.Port}";
|
model.Host = $"{external.BaseUri.DnsSafeHost}:{external.BaseUri.Port}";
|
||||||
model.SSL = external.BaseUri.Scheme == "https";
|
model.SSL = external.BaseUri.Scheme == "https";
|
||||||
model.ConnectionType = "GRPC";
|
model.ConnectionType = "GRPC";
|
||||||
|
model.GRPCSSLCipherSuites = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256";
|
||||||
}
|
}
|
||||||
else if(external.ConnectionType == LightningConnectionType.LndREST)
|
else if(external.ConnectionType == LightningConnectionType.LndREST)
|
||||||
{
|
{
|
||||||
|
@ -535,10 +585,10 @@ namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
model.Macaroon = Encoders.Hex.EncodeData(external.Macaroon);
|
model.Macaroon = Encoders.Hex.EncodeData(external.Macaroon);
|
||||||
}
|
}
|
||||||
if (external.RestrictedMacaroon != null)
|
var macaroons = external.MacaroonDirectoryPath == null ? null : await Macaroons.GetFromDirectoryAsync(external.MacaroonDirectoryPath);
|
||||||
{
|
model.AdminMacaroon = macaroons?.AdminMacaroon?.Hex;
|
||||||
model.RestrictedMacaroon = Encoders.Hex.EncodeData(external.RestrictedMacaroon);
|
model.InvoiceMacaroon = macaroons?.InvoiceMacaroon?.Hex;
|
||||||
}
|
model.ReadonlyMacaroon = macaroons?.ReadonlyMacaroon?.Hex;
|
||||||
|
|
||||||
if (nonce != null)
|
if (nonce != null)
|
||||||
{
|
{
|
||||||
|
@ -571,38 +621,40 @@ namespace BTCPayServer.Controllers
|
||||||
|
|
||||||
[Route("server/services/lnd/{cryptoCode}/{index}")]
|
[Route("server/services/lnd/{cryptoCode}/{index}")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult LndServicesPost(string cryptoCode, int index)
|
public async Task<IActionResult> LndServicesPost(string cryptoCode, int index)
|
||||||
{
|
{
|
||||||
var external = GetExternalLndConnectionString(cryptoCode, index);
|
var external = GetExternalLndConnectionString(cryptoCode, index);
|
||||||
if (external == null)
|
if (external == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
LightningConfigurations confs = new LightningConfigurations();
|
LightningConfigurations confs = new LightningConfigurations();
|
||||||
|
var macaroons = external.MacaroonDirectoryPath == null ? null : await Macaroons.GetFromDirectoryAsync(external.MacaroonDirectoryPath);
|
||||||
if (external.ConnectionType == LightningConnectionType.LndGRPC)
|
if (external.ConnectionType == LightningConnectionType.LndGRPC)
|
||||||
{
|
{
|
||||||
LightningConfiguration conf = new LightningConfiguration();
|
LightningConfiguration grpcConf = new LightningConfiguration();
|
||||||
conf.Type = "grpc";
|
grpcConf.Type = "grpc";
|
||||||
conf.ChainType = _Options.NetworkType.ToString();
|
grpcConf.Host = external.BaseUri.DnsSafeHost;
|
||||||
conf.CryptoCode = cryptoCode;
|
grpcConf.Port = external.BaseUri.Port;
|
||||||
conf.Host = external.BaseUri.DnsSafeHost;
|
grpcConf.SSL = external.BaseUri.Scheme == "https";
|
||||||
conf.Port = external.BaseUri.Port;
|
confs.Configurations.Add(grpcConf);
|
||||||
conf.SSL = external.BaseUri.Scheme == "https";
|
|
||||||
conf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon);
|
|
||||||
conf.RestrictedMacaroon = external.RestrictedMacaroon == null ? null : Encoders.Hex.EncodeData(external.RestrictedMacaroon);
|
|
||||||
conf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint);
|
|
||||||
confs.Configurations.Add(conf);
|
|
||||||
}
|
}
|
||||||
else if (external.ConnectionType == LightningConnectionType.LndREST)
|
else if (external.ConnectionType == LightningConnectionType.LndREST)
|
||||||
{
|
{
|
||||||
var restconf = new LNDRestConfiguration();
|
var restconf = new LNDRestConfiguration();
|
||||||
restconf.Type = "lnd-rest";
|
restconf.Type = "lnd-rest";
|
||||||
restconf.ChainType = _Options.NetworkType.ToString();
|
|
||||||
restconf.CryptoCode = cryptoCode;
|
|
||||||
restconf.Uri = external.BaseUri.AbsoluteUri;
|
restconf.Uri = external.BaseUri.AbsoluteUri;
|
||||||
restconf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon);
|
|
||||||
restconf.RestrictedMacaroon = external.RestrictedMacaroon == null ? null : Encoders.Hex.EncodeData(external.RestrictedMacaroon);
|
|
||||||
restconf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint);
|
|
||||||
confs.Configurations.Add(restconf);
|
confs.Configurations.Add(restconf);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw new NotSupportedException(external.ConnectionType.ToString());
|
||||||
|
var commonConf = (LNDConfiguration)confs.Configurations[confs.Configurations.Count - 1];
|
||||||
|
commonConf.ChainType = _Options.NetworkType.ToString();
|
||||||
|
commonConf.CryptoCode = cryptoCode;
|
||||||
|
commonConf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon);
|
||||||
|
commonConf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint);
|
||||||
|
commonConf.AdminMacaroon = macaroons?.AdminMacaroon?.Hex;
|
||||||
|
commonConf.ReadonlyMacaroon = macaroons?.ReadonlyMacaroon?.Hex;
|
||||||
|
commonConf.InvoiceMacaroon = macaroons?.InvoiceMacaroon?.Hex;
|
||||||
|
|
||||||
var nonce = RandomUtils.GetUInt32();
|
var nonce = RandomUtils.GetUInt32();
|
||||||
var configKey = GetConfigKey("lnd", cryptoCode, index, nonce);
|
var configKey = GetConfigKey("lnd", cryptoCode, index, nonce);
|
||||||
_LnConfigProvider.KeepConfig(configKey, confs);
|
_LnConfigProvider.KeepConfig(configKey, confs);
|
||||||
|
@ -628,18 +680,6 @@ namespace BTCPayServer.Controllers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (connectionString.RestrictedMacaroonFilePath != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
connectionString.RestrictedMacaroon = System.IO.File.ReadAllBytes(connectionString.RestrictedMacaroonFilePath);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Logs.Configuration.LogWarning($"{cryptoCode}: The restrictedmacaroon file path of the external LND grpc config was not found ({connectionString.RestrictedMacaroonFilePath})");
|
|
||||||
}
|
|
||||||
connectionString.RestrictedMacaroonFilePath = null;
|
|
||||||
}
|
|
||||||
return connectionString;
|
return connectionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,13 @@ namespace BTCPayServer
|
||||||
request.Path.ToUriComponent());
|
request.Path.ToUriComponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
|
||||||
|
/// If 'toto' and RootPath is empty returns '/toto'
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static string GetRelativePath(this HttpRequest request, string path)
|
public static string GetRelativePath(this HttpRequest request, string path)
|
||||||
{
|
{
|
||||||
if (path.Length > 0 && path[0] != '/')
|
if (path.Length > 0 && path[0] != '/')
|
||||||
|
@ -177,6 +184,25 @@ namespace BTCPayServer
|
||||||
path);
|
path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If 'https://example.com/toto' returns 'https://example.com/toto'
|
||||||
|
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
|
||||||
|
/// If 'toto' and RootPath is empty returns '/toto'
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetRelativePathOrAbsolute(this HttpRequest request, string path)
|
||||||
|
{
|
||||||
|
if (Uri.TryCreate(path, UriKind.Absolute, out var unused))
|
||||||
|
return path;
|
||||||
|
if (path.Length > 0 && path[0] != '/')
|
||||||
|
path = $"/{path}";
|
||||||
|
return string.Concat(
|
||||||
|
request.PathBase.ToUriComponent(),
|
||||||
|
path);
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetAbsoluteUri(this HttpRequest request, string redirectUrl)
|
public static string GetAbsoluteUri(this HttpRequest request, string redirectUrl)
|
||||||
{
|
{
|
||||||
bool isRelative =
|
bool isRelative =
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Models.ServerViewModels
|
||||||
|
{
|
||||||
|
public class ChargeServiceViewModel
|
||||||
|
{
|
||||||
|
public string Uri { get; set; }
|
||||||
|
public string APIToken { get; set; }
|
||||||
|
public string AuthenticatedUri { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,8 +11,12 @@ namespace BTCPayServer.Models.ServerViewModels
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
public bool SSL { get; set; }
|
public bool SSL { get; set; }
|
||||||
public string Macaroon { get; set; }
|
public string Macaroon { get; set; }
|
||||||
public string RestrictedMacaroon { get; set; }
|
public string AdminMacaroon { get; set; }
|
||||||
|
public string ReadonlyMacaroon { get; set; }
|
||||||
|
public string InvoiceMacaroon { get; set; }
|
||||||
public string CertificateThumbprint { get; set; }
|
public string CertificateThumbprint { get; set; }
|
||||||
|
[Display(Name = "GRPC SSL Cipher suite (GRPC_SSL_CIPHER_SUITES)")]
|
||||||
|
public string GRPCSSLCipherSuites { get; set; }
|
||||||
public string QRCode { get; set; }
|
public string QRCode { get; set; }
|
||||||
public string QRCodeLink { get; set; }
|
public string QRCodeLink { get; set; }
|
||||||
[Display(Name = "REST Uri")]
|
[Display(Name = "REST Uri")]
|
||||||
|
|
|
@ -78,5 +78,15 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BitcoinAddress GetDestination(BTCPayNetwork network)
|
||||||
|
{
|
||||||
|
return Output.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
string CryptoPaymentData.GetDestination(BTCPayNetwork network)
|
||||||
|
{
|
||||||
|
return GetDestination(network).ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,12 @@ namespace BTCPayServer.Payments.Lightning
|
||||||
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
||||||
public LightMoney Amount { get; set; }
|
public LightMoney Amount { get; set; }
|
||||||
public string BOLT11 { get; set; }
|
public string BOLT11 { get; set; }
|
||||||
|
|
||||||
|
public string GetDestination(BTCPayNetwork network)
|
||||||
|
{
|
||||||
|
return GetPaymentId();
|
||||||
|
}
|
||||||
|
|
||||||
public string GetPaymentId()
|
public string GetPaymentId()
|
||||||
{
|
{
|
||||||
return BOLT11;
|
return BOLT11;
|
||||||
|
|
|
@ -156,7 +156,8 @@ namespace BTCPayServer.Payments.Lightning
|
||||||
if (notification.Id == listenedInvoice.PaymentMethodDetails.InvoiceId &&
|
if (notification.Id == listenedInvoice.PaymentMethodDetails.InvoiceId &&
|
||||||
notification.BOLT11 == listenedInvoice.PaymentMethodDetails.BOLT11)
|
notification.BOLT11 == listenedInvoice.PaymentMethodDetails.BOLT11)
|
||||||
{
|
{
|
||||||
if (notification.Status == LightningInvoiceStatus.Paid && notification.PaidAt.HasValue)
|
if (notification.Status == LightningInvoiceStatus.Paid &&
|
||||||
|
notification.PaidAt.HasValue && notification.Amount != null)
|
||||||
{
|
{
|
||||||
await AddPayment(network, notification, listenedInvoice);
|
await AddPayment(network, notification, listenedInvoice);
|
||||||
if (DoneListening(listenedInvoice))
|
if (DoneListening(listenedInvoice))
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
"BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true",
|
"BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true",
|
||||||
"BTCPAY_BTCEXTERNALLNDREST": "type=lnd-rest;server=https://lnd:lnd@127.0.0.1:53280/lnd-rest/btc/;allowinsecure=true",
|
"BTCPAY_BTCEXTERNALLNDREST": "type=lnd-rest;server=https://lnd:lnd@127.0.0.1:53280/lnd-rest/btc/;allowinsecure=true",
|
||||||
"BTCPAY_BTCEXTERNALSPARK": "server=https://127.0.0.1:53280/spark/btc/;cookiefile=fake",
|
"BTCPAY_BTCEXTERNALSPARK": "server=https://127.0.0.1:53280/spark/btc/;cookiefile=fake",
|
||||||
|
"BTCPAY_BTCEXTERNALCHARGE": "server=https://127.0.0.1:53280/spark/btc/;cookiefilepath=fake",
|
||||||
"BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/",
|
"BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
"BTCPAY_CHAINS": "btc,ltc",
|
"BTCPAY_CHAINS": "btc,ltc",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Payments.Bitcoin;
|
using BTCPayServer.Payments.Bitcoin;
|
||||||
|
@ -10,6 +11,12 @@ namespace BTCPayServer.Services.Invoices.Export
|
||||||
{
|
{
|
||||||
public class InvoiceExport
|
public class InvoiceExport
|
||||||
{
|
{
|
||||||
|
public BTCPayNetworkProvider Networks { get; }
|
||||||
|
|
||||||
|
public InvoiceExport(BTCPayNetworkProvider networks)
|
||||||
|
{
|
||||||
|
Networks = networks;
|
||||||
|
}
|
||||||
public string Process(InvoiceEntity[] invoices, string fileFormat)
|
public string Process(InvoiceEntity[] invoices, string fileFormat)
|
||||||
{
|
{
|
||||||
var csvInvoices = new List<ExportInvoiceHolder>();
|
var csvInvoices = new List<ExportInvoiceHolder>();
|
||||||
|
@ -55,9 +62,7 @@ namespace BTCPayServer.Services.Invoices.Export
|
||||||
var cryptoCode = payment.GetPaymentMethodId().CryptoCode;
|
var cryptoCode = payment.GetPaymentMethodId().CryptoCode;
|
||||||
var pdata = payment.GetCryptoPaymentData();
|
var pdata = payment.GetCryptoPaymentData();
|
||||||
|
|
||||||
var pmethod = invoice.GetPaymentMethod(payment.GetPaymentMethodId(), null);
|
var pmethod = invoice.GetPaymentMethod(payment.GetPaymentMethodId(), Networks);
|
||||||
var accounting = pmethod.Calculate();
|
|
||||||
var details = pmethod.GetPaymentMethodDetails();
|
|
||||||
|
|
||||||
var target = new ExportInvoiceHolder
|
var target = new ExportInvoiceHolder
|
||||||
{
|
{
|
||||||
|
@ -65,27 +70,24 @@ namespace BTCPayServer.Services.Invoices.Export
|
||||||
PaymentId = pdata.GetPaymentId(),
|
PaymentId = pdata.GetPaymentId(),
|
||||||
CryptoCode = cryptoCode,
|
CryptoCode = cryptoCode,
|
||||||
ConversionRate = pmethod.Rate,
|
ConversionRate = pmethod.Rate,
|
||||||
PaymentType = details.GetPaymentType() == Payments.PaymentTypes.BTCLike ? "OnChain" : "OffChain",
|
PaymentType = payment.GetPaymentMethodId().PaymentType == Payments.PaymentTypes.BTCLike ? "OnChain" : "OffChain",
|
||||||
Destination = details.GetPaymentDestination(),
|
Destination = payment.GetCryptoPaymentData().GetDestination(Networks.GetNetwork(cryptoCode)),
|
||||||
PaymentDue = $"{accounting.MinimumTotalDue}",
|
Paid = pdata.GetValue().ToString(CultureInfo.InvariantCulture),
|
||||||
PaymentPaid = $"{accounting.CryptoPaid}",
|
|
||||||
PaymentOverpaid = $"{accounting.OverpaidHelper}",
|
|
||||||
|
|
||||||
OrderId = invoice.OrderId,
|
OrderId = invoice.OrderId,
|
||||||
StoreId = invoice.StoreId,
|
StoreId = invoice.StoreId,
|
||||||
InvoiceId = invoice.Id,
|
InvoiceId = invoice.Id,
|
||||||
CreatedDate = invoice.InvoiceTime.UtcDateTime,
|
InvoiceCreatedDate = invoice.InvoiceTime.UtcDateTime,
|
||||||
ExpirationDate = invoice.ExpirationTime.UtcDateTime,
|
InvoiceExpirationDate = invoice.ExpirationTime.UtcDateTime,
|
||||||
MonitoringDate = invoice.MonitoringExpiration.UtcDateTime,
|
InvoiceMonitoringDate = invoice.MonitoringExpiration.UtcDateTime,
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
FullStatus = invoice.Status.ToString(),
|
InvoiceFullStatus = invoice.GetInvoiceState().ToString(),
|
||||||
Status = invoice.StatusString,
|
InvoiceStatus = invoice.StatusString,
|
||||||
ExceptionStatus = invoice.ExceptionStatusString,
|
InvoiceExceptionStatus = invoice.ExceptionStatusString,
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
ItemCode = invoice.ProductInformation?.ItemCode,
|
InvoiceItemCode = invoice.ProductInformation.ItemCode,
|
||||||
ItemDesc = invoice.ProductInformation?.ItemDesc,
|
InvoiceItemDesc = invoice.ProductInformation.ItemDesc,
|
||||||
FiatPrice = invoice.ProductInformation?.Price ?? 0,
|
InvoicePrice = invoice.ProductInformation.Price,
|
||||||
FiatCurrency = invoice.ProductInformation?.Currency,
|
InvoiceCurrency = invoice.ProductInformation.Currency,
|
||||||
};
|
};
|
||||||
|
|
||||||
exportList.Add(target);
|
exportList.Add(target);
|
||||||
|
@ -103,25 +105,23 @@ namespace BTCPayServer.Services.Invoices.Export
|
||||||
public string StoreId { get; set; }
|
public string StoreId { get; set; }
|
||||||
public string OrderId { get; set; }
|
public string OrderId { get; set; }
|
||||||
public string InvoiceId { get; set; }
|
public string InvoiceId { get; set; }
|
||||||
public DateTime CreatedDate { get; set; }
|
public DateTime InvoiceCreatedDate { get; set; }
|
||||||
public DateTime ExpirationDate { get; set; }
|
public DateTime InvoiceExpirationDate { get; set; }
|
||||||
public DateTime MonitoringDate { get; set; }
|
public DateTime InvoiceMonitoringDate { get; set; }
|
||||||
|
|
||||||
public string PaymentId { get; set; }
|
public string PaymentId { get; set; }
|
||||||
public string CryptoCode { get; set; }
|
|
||||||
public string Destination { get; set; }
|
public string Destination { get; set; }
|
||||||
public string PaymentType { get; set; }
|
public string PaymentType { get; set; }
|
||||||
public string PaymentDue { get; set; }
|
public string Paid { get; set; }
|
||||||
public string PaymentPaid { get; set; }
|
public string CryptoCode { get; set; }
|
||||||
public string PaymentOverpaid { get; set; }
|
|
||||||
public decimal ConversionRate { get; set; }
|
public decimal ConversionRate { get; set; }
|
||||||
|
|
||||||
public decimal FiatPrice { get; set; }
|
public decimal InvoicePrice { get; set; }
|
||||||
public string FiatCurrency { get; set; }
|
public string InvoiceCurrency { get; set; }
|
||||||
public string ItemCode { get; set; }
|
public string InvoiceItemCode { get; set; }
|
||||||
public string ItemDesc { get; set; }
|
public string InvoiceItemDesc { get; set; }
|
||||||
public string FullStatus { get; set; }
|
public string InvoiceFullStatus { get; set; }
|
||||||
public string Status { get; set; }
|
public string InvoiceStatus { get; set; }
|
||||||
public string ExceptionStatus { get; set; }
|
public string InvoiceExceptionStatus { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -982,5 +982,6 @@ namespace BTCPayServer.Services.Invoices
|
||||||
bool PaymentConfirmed(PaymentEntity entity, SpeedPolicy speedPolicy, BTCPayNetwork network);
|
bool PaymentConfirmed(PaymentEntity entity, SpeedPolicy speedPolicy, BTCPayNetwork network);
|
||||||
|
|
||||||
PaymentTypes GetPaymentType();
|
PaymentTypes GetPaymentType();
|
||||||
|
string GetDestination(BTCPayNetwork network);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
using NBitcoin.DataEncoders;
|
||||||
|
|
||||||
namespace BTCPayServer.Services
|
namespace BTCPayServer.Services
|
||||||
{
|
{
|
||||||
|
@ -27,9 +28,9 @@ namespace BTCPayServer.Services
|
||||||
|
|
||||||
private void CleanExpired()
|
private void CleanExpired()
|
||||||
{
|
{
|
||||||
foreach(var item in _Map)
|
foreach (var item in _Map)
|
||||||
{
|
{
|
||||||
if(item.Value.expiration < DateTimeOffset.UtcNow)
|
if (item.Value.expiration < DateTimeOffset.UtcNow)
|
||||||
{
|
{
|
||||||
_Map.TryRemove(item.Key, out var unused);
|
_Map.TryRemove(item.Key, out var unused);
|
||||||
}
|
}
|
||||||
|
@ -41,26 +42,26 @@ namespace BTCPayServer.Services
|
||||||
{
|
{
|
||||||
public List<object> Configurations { get; set; } = new List<object>();
|
public List<object> Configurations { get; set; } = new List<object>();
|
||||||
}
|
}
|
||||||
public class LightningConfiguration
|
|
||||||
|
public class LNDConfiguration
|
||||||
{
|
{
|
||||||
public string ChainType { get; set; }
|
public string ChainType { get; set; }
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
public string CryptoCode { get; set; }
|
public string CryptoCode { get; set; }
|
||||||
|
public string CertificateThumbprint { get; set; }
|
||||||
|
public string Macaroon { get; set; }
|
||||||
|
public string AdminMacaroon { get; set; }
|
||||||
|
public string ReadonlyMacaroon { get; set; }
|
||||||
|
public string InvoiceMacaroon { get; set; }
|
||||||
|
}
|
||||||
|
public class LightningConfiguration : LNDConfiguration
|
||||||
|
{
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public bool SSL { get; set; }
|
public bool SSL { get; set; }
|
||||||
public string CertificateThumbprint { get; set; }
|
|
||||||
public string Macaroon { get; set; }
|
|
||||||
public string RestrictedMacaroon { get; set; }
|
|
||||||
}
|
}
|
||||||
public class LNDRestConfiguration
|
public class LNDRestConfiguration : LNDConfiguration
|
||||||
{
|
{
|
||||||
public string ChainType { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string CryptoCode { get; set; }
|
|
||||||
public string Uri { get; set; }
|
public string Uri { get; set; }
|
||||||
public string Macaroon { get; set; }
|
|
||||||
public string CertificateThumbprint { get; set; }
|
|
||||||
public string RestrictedMacaroon { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
<div class="header-content-inner text-white">
|
<div class="header-content-inner text-white">
|
||||||
<h1>Welcome to BTCPay Server</h1>
|
<h1>Welcome to BTCPay Server</h1>
|
||||||
<hr />
|
<hr />
|
||||||
<p>BTCPay Server is a free and open source server for merchants wanting to accept Bitcoin for their business. The API is compatible with Bitpay service to allow seamless migration.</p>
|
<p>BTCPay Server is a free and open source server for merchants wanting to accept Bitcoin for their business.</p>
|
||||||
<a style="background-color: #fff;color: #222;display:inline-block;text-align: center;white-space: nowrap;vertical-align: middle;user-select: none;line-height: 1.25;font-size: 1rem;text-decoration:none;font-weight: 700; text-transform: uppercase;border: none;border-radius: 300px;padding: 15px 30px;" href="https://github.com/btcpayserver/btcpayserver-doc">Getting started</a>
|
<a style="background-color: #fff;color: #222;display:inline-block;text-align: center;white-space: nowrap;vertical-align: middle;user-select: none;line-height: 1.25;font-size: 1rem;text-decoration:none;font-weight: 700; text-transform: uppercase;border: none;border-radius: 300px;padding: 15px 30px;" href="https://docs.btcpayserver.org">Getting started</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
60
BTCPayServer/Views/Server/LightningChargeServices.cshtml
Normal file
60
BTCPayServer/Views/Server/LightningChargeServices.cshtml
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
@model ChargeServiceViewModel
|
||||||
|
@{
|
||||||
|
ViewData.SetActivePageAndTitle(ServerNavPages.Services);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Lightning charge service</h4>
|
||||||
|
<partial name="_StatusMessage" for="@TempData["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>Lightning charge is a simple API for invoicing on lightning network, you can use it with several plugins:</span>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://github.com/ElementsProject/woocommerce-gateway-lightning" target="_blank">WooCommerce Lightning Gateway</a>: A comprehensive e-commerce application that integrates with stock-management and order-tracking systems</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/nanopos" target="_blank">Nanopos</a>: A simple point-of-sale system for fixed-price goods</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/filebazaar" target="_blank">FileBazaar</a>: A system for selling files such as documents, images, and videos</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/wordpress-lightning-publisher" target="_blank">Lightning Publisher for WordPress</a>: A patronage model for unlocking WordPress blog entries</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/paypercall" target="_blank">Paypercall</a>: A programmer’s toolkit for Lightning that enables micropayments for individual API calls</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/ifpaytt" target="_blank">Ifpaytt</a>: An extension of paypercall that allows web developers using IFTTT to request payments for service usage</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/lightning-jukebox" target="_blank">Lightning Jukebox</a>: A fun demo that reimagines a classic technology for the Lightning Network</li>
|
||||||
|
<li><a href="https://github.com/ElementsProject/nanotip" target="_blank">Nanotip</a>: The simple tip jar, rebuilt to issue Lightning Network invoices</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h4>Credentials</h4>
|
||||||
|
@if (Model.Uri != null)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Uri"></label>
|
||||||
|
<input asp-for="Uri" readonly class="form-control" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.APIToken != null)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="APIToken"></label>
|
||||||
|
<input asp-for="APIToken" readonly class="form-control" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.AuthenticatedUri != null)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="AuthenticatedUri"></label>
|
||||||
|
<input asp-for="AuthenticatedUri" readonly class="form-control" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -86,12 +86,33 @@
|
||||||
<input asp-for="Macaroon" readonly class="form-control" />
|
<input asp-for="Macaroon" readonly class="form-control" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (Model.RestrictedMacaroon != null)
|
@if (Model.AdminMacaroon != null)
|
||||||
{
|
{
|
||||||
@*<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="RestrictedMacaroon"></label>
|
<label asp-for="AdminMacaroon"></label>
|
||||||
<input asp-for="RestrictedMacaroon" readonly class="form-control" />
|
<input asp-for="AdminMacaroon" readonly class="form-control" />
|
||||||
</div>*@
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.InvoiceMacaroon != null)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="InvoiceMacaroon"></label>
|
||||||
|
<input asp-for="InvoiceMacaroon" readonly class="form-control" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.ReadonlyMacaroon != null)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="ReadonlyMacaroon"></label>
|
||||||
|
<input asp-for="ReadonlyMacaroon" readonly class="form-control" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.GRPCSSLCipherSuites != null)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="GRPCSSLCipherSuites"></label>
|
||||||
|
<input asp-for="GRPCSSLCipherSuites" readonly class="form-control" />
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
@if (Model.CertificateThumbprint != null)
|
@if (Model.CertificateThumbprint != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
<title>BTCPay Server</title>
|
<title>BTCPay Server</title>
|
||||||
|
|
||||||
@* CSS *@
|
@* CSS *@
|
||||||
<link href="@this.Context.Request.GetAbsoluteUri(themeManager.BootstrapUri)" rel="stylesheet" />
|
<link href="@this.Context.Request.GetRelativePathOrAbsolute(themeManager.BootstrapUri)" rel="stylesheet" />
|
||||||
<link href="@this.Context.Request.GetAbsoluteUri(themeManager.CreativeStartUri)" rel="stylesheet" />
|
<link href="@this.Context.Request.GetRelativePathOrAbsolute(themeManager.CreativeStartUri)" rel="stylesheet" />
|
||||||
|
|
||||||
<bundle name="wwwroot/bundles/main-bundle.min.css" />
|
<bundle name="wwwroot/bundles/main-bundle.min.css" />
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 93 KiB |
54
BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.svg
Normal file
54
BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.svg
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="1000px" height="1000px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||||
|
<g id="Groestlcoin_LN">
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M286.425,653.96"/>
|
||||||
|
<g>
|
||||||
|
<polygon fill="#FFFFFF" points="603.786,724.791 601.652,728.634 601.652,728.634 "/>
|
||||||
|
<path fill="#FFFFFF" d="M502.935,79.215c-46.6,0-91.46,7.565-133.443,21.495L243.38,13.165l-14.07,17.69l96.15,87.27
|
||||||
|
C179.64,185.465,78.2,333.075,78.2,503.95c0,234.2,190.535,424.733,424.733,424.733c50.125,0,98.24-8.755,142.927-24.77
|
||||||
|
l-32.592-22.73c-35.02,10.262-72.038,15.79-110.335,15.79c-216.714,0-393.023-176.31-393.023-393.023
|
||||||
|
c0-162.935,99.665-303.02,241.229-362.515c3.025-1.27,3.025-1.27,0,0l244.506,221.93L460.67,634.56l148.255,132.08l-5.14-41.903
|
||||||
|
l-2.135,3.845l2.135-3.845l-13.28-108.262l134.37-269.043l-322.04-223.565c31.97-8.425,65.521-12.935,100.101-12.935
|
||||||
|
c216.716,0,393.024,176.31,393.024,393.025c0,160.175-96.325,298.26-234.085,359.415l25.775,23.005
|
||||||
|
c141.925-68.83,240.02-214.38,240.02-382.42C927.67,269.75,737.135,79.215,502.935,79.215z"/>
|
||||||
|
</g>
|
||||||
|
<path fill="#FFFFFF" d="M687.65,886.375l-25.775-23.005c-3.925,1.74-3.925,1.74,0,0L409.78,638.36l135.08-271.985L396.12,232.45
|
||||||
|
l-0.555,1.19L418.38,391.2l0,0L288.575,654.75l324.688,226.435l32.592,22.73l126.01,87.88l14.02-17.74L687.65,886.375z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M286.425,653.96"/>
|
||||||
|
<g>
|
||||||
|
<polygon fill="#FFFFFF" points="603.786,724.791 601.652,728.634 601.652,728.634 "/>
|
||||||
|
<path fill="#FFFFFF" d="M502.935,79.215c-46.6,0-91.46,7.565-133.443,21.495L243.38,13.165l-14.07,17.69l96.15,87.27
|
||||||
|
C179.64,185.465,78.2,333.075,78.2,503.95c0,234.2,190.535,424.733,424.733,424.733c50.125,0,98.24-8.755,142.927-24.77
|
||||||
|
l-32.592-22.73c-35.02,10.262-72.038,15.79-110.335,15.79c-216.714,0-393.023-176.31-393.023-393.023
|
||||||
|
c0-162.935,99.665-303.02,241.229-362.515c3.025-1.27,3.025-1.27,0,0l244.506,221.93L460.67,634.56l148.255,132.08l-5.14-41.903
|
||||||
|
l-2.135,3.845l2.135-3.845l-13.28-108.262l134.37-269.043l-322.04-223.565c31.97-8.425,65.521-12.935,100.101-12.935
|
||||||
|
c216.716,0,393.024,176.31,393.024,393.025c0,160.175-96.325,298.26-234.085,359.415l25.775,23.005
|
||||||
|
c141.925-68.83,240.02-214.38,240.02-382.42C927.67,269.75,737.135,79.215,502.935,79.215z"/>
|
||||||
|
</g>
|
||||||
|
<path fill="#FFFFFF" d="M687.65,886.375l-25.775-23.005c-3.925,1.74-3.925,1.74,0,0L409.78,638.36l135.08-271.985L396.12,232.45
|
||||||
|
l-0.555,1.19L418.38,391.2l0,0L288.575,654.75l324.688,226.435l32.592,22.73l126.01,87.88l14.02-17.74L687.65,886.375z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M286.425,653.96"/>
|
||||||
|
<g>
|
||||||
|
<circle fill="#FFFFFF" cx="510" cy="500" r="408.335"/>
|
||||||
|
<polygon fill="#FFFFFF" points="603.786,724.791 601.652,728.634 601.652,728.634 "/>
|
||||||
|
<path fill="#009CCD" d="M502.935,79.215c-46.6,0-91.46,7.565-133.443,21.495L243.38,13.165l-14.07,17.69l96.15,87.27
|
||||||
|
C179.64,185.465,78.2,333.075,78.2,503.95c0,234.2,190.535,424.733,424.733,424.733c50.125,0,98.24-8.755,142.927-24.77
|
||||||
|
l-32.592-22.73c-35.02,10.262-72.038,15.79-110.335,15.79c-216.714,0-393.023-176.31-393.023-393.023
|
||||||
|
c0-162.935,99.665-303.02,241.229-362.515c3.025-1.27,3.025-1.27,0,0l244.506,221.93L460.67,634.56l148.255,132.08l-5.14-41.903
|
||||||
|
l-2.135,3.845l2.135-3.845l-13.28-108.262l134.37-269.043l-322.04-223.565c31.97-8.425,65.521-12.935,100.101-12.935
|
||||||
|
c216.716,0,393.024,176.31,393.024,393.025c0,160.175-96.325,298.26-234.085,359.415l25.775,23.005
|
||||||
|
c141.925-68.83,240.02-214.38,240.02-382.42C927.67,269.75,737.135,79.215,502.935,79.215z"/>
|
||||||
|
</g>
|
||||||
|
<path fill="#006694" d="M687.65,886.375l-25.775-23.005c-3.925,1.74-3.925,1.74,0,0L409.78,638.36l135.08-271.985L396.12,232.45
|
||||||
|
l-0.555,1.19L418.38,391.2l0,0L288.575,654.75l324.688,226.435l32.592,22.73l126.01,87.88l14.02-17.74L687.65,886.375z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4 KiB |
|
@ -22,12 +22,12 @@
|
||||||
"Amount": "Cantidad",
|
"Amount": "Cantidad",
|
||||||
"Address": "Dirección",
|
"Address": "Dirección",
|
||||||
"Copied": "Copiado",
|
"Copied": "Copiado",
|
||||||
"ConversionTab_BodyTop": "Puedes pagar {{btcDue}} {{cryptoCode}} usando Altcoins que este comercio no soporta directamente.",
|
"ConversionTab_BodyTop": "Puedes pagar {{btcDue}} {{cryptoCode}} usando altcoins que este comercio no soporta directamente.",
|
||||||
"ConversionTab_BodyDesc": "Este servicio es provisto por terceros. Ten en cuenta que no tenemos control sobre cómo estos terceros envían los fondos. La factura solo se marcará como pagada una vez se reciban los fondos en la cadena de bloques de {{cryptoCode}} .",
|
"ConversionTab_BodyDesc": "Este servicio es provisto por terceros. Ten en cuenta que no tenemos control sobre cómo estos terceros envían los fondos. La factura solo se marcará como pagada una vez se reciban los fondos en la cadena de bloques de {{cryptoCode}} .",
|
||||||
"ConversionTab_CalculateAmount_Error": "Reintentar",
|
"ConversionTab_CalculateAmount_Error": "Reintentar",
|
||||||
"ConversionTab_LoadCurrencies_Error": "Reintentar",
|
"ConversionTab_LoadCurrencies_Error": "Reintentar",
|
||||||
"ConversionTab_Lightning": "No hay proveedores de conversión disponibles para los pagos de Lightning Network.",
|
"ConversionTab_Lightning": "No hay proveedores de conversión disponibles para los pagos de Lightning Network.",
|
||||||
"ConversionTab_CurrencyList_Select_Option": "Por favor selecciona el tipo de moneda que de desea cambiar",
|
"ConversionTab_CurrencyList_Select_Option": "Selecciona la moneda a convertir",
|
||||||
"Invoice expiring soon...": "La factura expira pronto...",
|
"Invoice expiring soon...": "La factura expira pronto...",
|
||||||
"Invoice expired": "La factura expiró",
|
"Invoice expired": "La factura expiró",
|
||||||
"What happened?": "¿Qué sucedió?",
|
"What happened?": "¿Qué sucedió?",
|
||||||
|
|
47
BTCPayServer/wwwroot/locales/tr.json
Normal file
47
BTCPayServer/wwwroot/locales/tr.json
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"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": "tr",
|
||||||
|
"currentLanguage": "Türkçe",
|
||||||
|
"lang": "Dil",
|
||||||
|
"Awaiting Payment...": "Ödeme Bekleniyor...",
|
||||||
|
"Pay with": "Aracılığıyla Öde",
|
||||||
|
"Contact and Refund Email": "İletişim ve Geri Ödeme Email",
|
||||||
|
"Contact_Body": "Lütfen aşağıda bir email belirtin. Ödemede sorun olması halinde bu adresten sizinle iletişime geçeceğiz.",
|
||||||
|
"Your email": "Email Adresiniz",
|
||||||
|
"Continue": "Devam Et",
|
||||||
|
"Please enter a valid email address": "Lütfen geçerli bir email adresi giriniz",
|
||||||
|
"Order Amount": "Ödeme Tutarı",
|
||||||
|
"Network Cost": "Ağ Ücreti",
|
||||||
|
"Already Paid": "Zaten Ödendi",
|
||||||
|
"Due": "Bitiş Tarihi",
|
||||||
|
"Scan": "Tara",
|
||||||
|
"Copy": "Kopyala",
|
||||||
|
"Conversion": "Dönüştürme",
|
||||||
|
"Open in wallet": "Cüzdanda Aç",
|
||||||
|
"CompletePay_Body": "Ödemenizi tamamlamak için, lütfen {{btcDue}} {{cryptoCode}} bilgilerini aşağıdaki adrese gönderin.",
|
||||||
|
"Amount": "Tutar",
|
||||||
|
"Address": "Adres",
|
||||||
|
"Copied": "Kopyalandı",
|
||||||
|
"ConversionTab_BodyTop": "{{btcDue}} {{cryptoCode}} ödemenizi satıcının desteklemediği altcoinler ile de yapabilirsiniz.",
|
||||||
|
"ConversionTab_BodyDesc": "Bu servis 3. kişiler tarafından sağlanmaktadır. Ödemelerinizin iletildiği sağlayıcılar üzerinde bizim herhangi bir yetkimiz bulunmamaktadır. Faturanın ödendi olarak işaretlenmesi için ödemenin {{cryptoCode}} Blockchain ağından gelmesi gerekmektedir.",
|
||||||
|
"ConversionTab_CalculateAmount_Error": "Tekar dene",
|
||||||
|
"ConversionTab_LoadCurrencies_Error": "Tekrar dene",
|
||||||
|
"ConversionTab_Lightning": "Lightning Network ödemesi için dönüşüm sağlayıcı mevcut değil.",
|
||||||
|
"ConversionTab_CurrencyList_Select_Option": "Lütfen çevrim için bir para birimi seçin",
|
||||||
|
"Invoice expiring soon...": "Fatura son kullanım tarihi yakın...",
|
||||||
|
"Invoice expired": "Fatura son kullanım tarihi geçti",
|
||||||
|
"What happened?": "Ne oldu?",
|
||||||
|
"InvoiceExpired_Body_1": "Bu Fatura'nın son kullanım tarihi doldu. Bir Fatura sadece {{maxTimeMinutes}} dakika geçerlidir.\nÖdemenizi tekrar göndermek istiyorsanız {{storeName}} mağazasına dönebilirsiniz.",
|
||||||
|
"InvoiceExpired_Body_2": "Ödemenizi göndermeyi denediyseniz, ağ tarafından henüz onaylanmadı. Ödemeniz bize ulaşmadı.",
|
||||||
|
"InvoiceExpired_Body_3": "Eğer daha sonra bize ulaşırsa, ya siparişinizi onaylarız ya da iade için sizinle iletişime geçeriz.",
|
||||||
|
"Invoice ID": "Fatura ID",
|
||||||
|
"Order ID": "Sipariş ID",
|
||||||
|
"Return to StoreName": "{{storeName}} dön",
|
||||||
|
"This invoice has been paid": "Bu Fatura ödendi",
|
||||||
|
"This invoice has been archived": "Bu Fatura arşivlendi",
|
||||||
|
"Archived_Body": "Bilgi ve yardım için lütfen mağaza ile iletişime geçin",
|
||||||
|
"BOLT 11 Invoice": "BOLT 11 Faturası",
|
||||||
|
"Node Info": "Düğüm Bilgisi",
|
||||||
|
"txCount": "{{count}} işlem",
|
||||||
|
"txCount_plural": "{{count}} işlem"
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue