rebrand(lethean): update branding, ports, and config for Lethean blockchain
- Coin: Zano → Lethean, ticker: ZAN/ZANO → LTHN - Ports: 11211 → 36941 (mainnet RPC), 46941 (testnet RPC) - Wallet: 11212 → 36944/46944 - Address prefix: iTHN - URLs: zano.org → lethean.io - Explorer links: explorer.lthn.io Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d51d7dc0c0
commit
a3869db496
75 changed files with 699 additions and 699 deletions
2
.github/workflows/codacy.yml
vendored
2
.github/workflows/codacy.yml
vendored
|
|
@ -13,7 +13,7 @@ permissions:
|
|||
|
||||
jobs:
|
||||
report-coverage:
|
||||
if: github.repository == 'btcpay-zano/btcpayserver-zano-plugin'
|
||||
if: github.repository == 'btcpay-lethean/btcpayserver-lethean-plugin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download coverage report
|
||||
|
|
|
|||
2
.github/workflows/dotnet-format.yml
vendored
2
.github/workflows/dotnet-format.yml
vendored
|
|
@ -29,4 +29,4 @@ jobs:
|
|||
- name: Code format check
|
||||
run: |
|
||||
dotnet tool install -g dotnet-format
|
||||
dotnet format btcpay-zano-plugin.sln --no-restore --verify-no-changes --exclude submodules/* --verbosity diagnostic
|
||||
dotnet format btcpay-lethean-plugin.sln --no-restore --verify-no-changes --exclude submodules/* --verbosity diagnostic
|
||||
6
.github/workflows/dotnet.yml
vendored
6
.github/workflows/dotnet.yml
vendored
|
|
@ -36,8 +36,8 @@ jobs:
|
|||
- name: Deterministic build check
|
||||
run: |
|
||||
dotnet tool install --global dotnet-validate --version 0.0.1-preview.537
|
||||
dotnet pack Plugins/Zano/BTCPayServer.Plugins.Zano.csproj -c Release /p:PackageVersion=1 --no-build -o nuget-packages
|
||||
dotnet validate package local nuget-packages/BTCPayServer.Plugins.Zano.1.0.0.nupkg
|
||||
dotnet pack Plugins/Lethean/BTCPayServer.Plugins.Lethean.csproj -c Release /p:PackageVersion=1 --no-build -o nuget-packages
|
||||
dotnet validate package local nuget-packages/BTCPayServer.Plugins.Lethean.1.0.0.nupkg
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
|
|
@ -61,4 +61,4 @@ jobs:
|
|||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nuget-package-${{ github.sha }}
|
||||
path: nuget-packages/BTCPayServer.Plugins.Zano.1.0.0.nupkg
|
||||
path: nuget-packages/BTCPayServer.Plugins.Lethean.1.0.0.nupkg
|
||||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
|
|
@ -25,4 +25,4 @@ jobs:
|
|||
"GitRef": "${{ env.GIT_REF }}"
|
||||
}'
|
||||
env:
|
||||
pluginSlug: "zano-plugin"
|
||||
pluginSlug: "lethean-plugin"
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\submodules\btcpayserver\BTCPayServer.Abstractions\BTCPayServer.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\submodules\btcpayserver\BTCPayServer.Tests\BTCPayServer.Tests.csproj" />
|
||||
<ProjectReference Include="..\Plugins\Zano\BTCPayServer.Plugins.Zano.csproj" />
|
||||
<ProjectReference Include="..\Plugins\Lethean\BTCPayServer.Plugins.Lethean.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ ENV SCREEN_HEIGHT 600 \
|
|||
COPY . .
|
||||
|
||||
ARG CONFIGURATION_NAME=Release
|
||||
ARG MONERO_PLUGIN_FOLDER=/root/.btcpayserver/Plugins/BTCPayServer.Plugins.Zano/
|
||||
ARG MONERO_PLUGIN_FOLDER=/root/.btcpayserver/Plugins/BTCPayServer.Plugins.Lethean/
|
||||
RUN mkdir -p ${MONERO_PLUGIN_FOLDER}
|
||||
RUN cd Plugins/Zano && dotnet build BTCPayServer.Plugins.Zano.sln --configuration ${CONFIGURATION_NAME} /p:RazorCompileOnBuild=true --output ${MONERO_PLUGIN_FOLDER}
|
||||
RUN cd Plugins/Lethean && dotnet build BTCPayServer.Plugins.Lethean.sln --configuration ${CONFIGURATION_NAME} /p:RazorCompileOnBuild=true --output ${MONERO_PLUGIN_FOLDER}
|
||||
RUN cd BTCPayServer.Plugins.IntegrationTests && dotnet build --configuration ${CONFIGURATION_NAME} /p:CI_TESTS=true /p:RazorCompileOnBuild=true
|
||||
RUN dotnet tool install --global JetBrains.DotCover.CommandLineTools --version 2025.1.6
|
||||
ENV PATH="$PATH:/root/.dotnet/tools"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using Npgsql;
|
|||
|
||||
using static Mono.Unix.Native.Syscall;
|
||||
|
||||
namespace BTCPayServer.Plugins.IntegrationTests.Zano;
|
||||
namespace BTCPayServer.Plugins.IntegrationTests.Lethean;
|
||||
|
||||
public static class IntegrationTestUtils
|
||||
{
|
||||
|
|
@ -19,7 +19,7 @@ public static class IntegrationTestUtils
|
|||
.CreateLogger("IntegrationTestUtils");
|
||||
|
||||
private static readonly string ContainerWalletDir =
|
||||
Environment.GetEnvironmentVariable("BTCPAY_ZANO_WALLET_DAEMON_WALLETDIR") ?? "/wallet";
|
||||
Environment.GetEnvironmentVariable("BTCPAY_LTHN_WALLET_DAEMON_WALLETDIR") ?? "/wallet";
|
||||
|
||||
public static async Task CleanUpAsync(PlaywrightTester playwrightTester)
|
||||
{
|
||||
|
|
@ -61,7 +61,7 @@ public static class IntegrationTestUtils
|
|||
}
|
||||
}
|
||||
|
||||
public static async Task CopyWalletFilesToZanoRpcDirAsync(PlaywrightTester playwrightTester, String walletDir)
|
||||
public static async Task CopyWalletFilesToLetheanRpcDirAsync(PlaywrightTester playwrightTester, String walletDir)
|
||||
{
|
||||
Logger.LogInformation("Starting to copy wallet files");
|
||||
if (playwrightTester.Server.PayTester.InContainer)
|
||||
|
|
@ -84,7 +84,7 @@ public static class IntegrationTestUtils
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Failed to copy wallet files to the Zano directory.");
|
||||
Logger.LogError(ex, "Failed to copy wallet files to the Lethean directory.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ public static class IntegrationTestUtils
|
|||
|
||||
File.Copy(src, dst, overwrite: true);
|
||||
|
||||
// zano ownership
|
||||
// lethean ownership
|
||||
if (chown(dst, 980, 980) == 0)
|
||||
{
|
||||
return;
|
||||
|
|
@ -119,20 +119,20 @@ public static class IntegrationTestUtils
|
|||
var fullWalletDir = Path.Combine(AppContext.BaseDirectory, "Resources", walletDir);
|
||||
|
||||
await RunProcessAsync("docker",
|
||||
$"cp \"{Path.Combine(fullWalletDir, "wallet")}\" zano_wallet:/wallet/wallet");
|
||||
$"cp \"{Path.Combine(fullWalletDir, "wallet")}\" lethean_wallet:/wallet/wallet");
|
||||
|
||||
await RunProcessAsync("docker",
|
||||
$"cp \"{Path.Combine(fullWalletDir, "wallet.keys")}\" zano_wallet:/wallet/wallet.keys");
|
||||
$"cp \"{Path.Combine(fullWalletDir, "wallet.keys")}\" lethean_wallet:/wallet/wallet.keys");
|
||||
|
||||
await RunProcessAsync("docker",
|
||||
$"cp \"{Path.Combine(fullWalletDir, "password")}\" zano_wallet:/wallet/password");
|
||||
$"cp \"{Path.Combine(fullWalletDir, "password")}\" lethean_wallet:/wallet/password");
|
||||
|
||||
await RunProcessAsync("docker",
|
||||
"exec zano_wallet chown zano:zano /wallet/wallet /wallet/wallet.keys /wallet/password");
|
||||
"exec lethean_wallet chown lethean:lethean /wallet/wallet /wallet/wallet.keys /wallet/password");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Failed to copy wallet files to the Zano directory.");
|
||||
Logger.LogError(ex, "Failed to copy wallet files to the Lethean directory.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ public static class IntegrationTestUtils
|
|||
var removeWalletFromDocker = new ProcessStartInfo
|
||||
{
|
||||
FileName = "docker",
|
||||
Arguments = "exec zano_wallet sh -c \"rm -rf /wallet/*\"",
|
||||
Arguments = "exec lethean_wallet sh -c \"rm -rf /wallet/*\"",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using BTCPayServer.Tests;
|
||||
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace BTCPayServer.Plugins.IntegrationTests.Lethean
|
||||
{
|
||||
public class LetheanAndBitcoinIntegrationTestBase : UnitTestBase
|
||||
{
|
||||
|
||||
public LetheanAndBitcoinIntegrationTestBase(ITestOutputHelper helper) : base(helper)
|
||||
{
|
||||
SetDefaultEnv("BTCPAY_LTHN_DAEMON_URI", "http://127.0.0.1:46941");
|
||||
SetDefaultEnv("BTCPAY_LTHN_WALLET_DAEMON_URI", "http://127.0.0.1:46944");
|
||||
SetDefaultEnv("BTCPAY_LTHN_WALLET_DAEMON_WALLETDIR", "/wallet");
|
||||
}
|
||||
|
||||
private static void SetDefaultEnv(string key, string defaultValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(key)))
|
||||
{
|
||||
Environment.SetEnvironmentVariable(key, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using BTCPayServer.Plugins.Zano.Services;
|
||||
using BTCPayServer.Plugins.Lethean.Services;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Tests.Mocks;
|
||||
|
|
@ -6,12 +6,12 @@ using BTCPayServer.Tests.Mocks;
|
|||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace BTCPayServer.Plugins.IntegrationTests.Zano;
|
||||
namespace BTCPayServer.Plugins.IntegrationTests.Lethean;
|
||||
|
||||
public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoinIntegrationTestBase(helper)
|
||||
public class LetheanPluginIntegrationTest(ITestOutputHelper helper) : LetheanAndBitcoinIntegrationTestBase(helper)
|
||||
{
|
||||
[Fact]
|
||||
public async Task ShouldEnableZanoPluginSuccessfully()
|
||||
public async Task ShouldEnableLetheanPluginSuccessfully()
|
||||
{
|
||||
await using var s = CreatePlaywrightTester();
|
||||
await s.StartAsync();
|
||||
|
|
@ -24,21 +24,21 @@ public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoi
|
|||
var coinAverageMock = new MockRateProvider();
|
||||
coinAverageMock.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("BTC_USD"), new BidAsk(5000m)));
|
||||
coinAverageMock.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("BTC_EUR"), new BidAsk(4000m)));
|
||||
coinAverageMock.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("ZANO_BTC"), new BidAsk(4500m)));
|
||||
coinAverageMock.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("LTHN_BTC"), new BidAsk(4500m)));
|
||||
rateProviderFactory.Providers.Add("coingecko", coinAverageMock);
|
||||
|
||||
var kraken = new MockRateProvider();
|
||||
kraken.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("BTC_USD"), new BidAsk(0.1m)));
|
||||
kraken.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("ZANO_USD"), new BidAsk(0.1m)));
|
||||
kraken.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("ZANO_BTC"), new BidAsk(0.1m)));
|
||||
kraken.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("LTHN_USD"), new BidAsk(0.1m)));
|
||||
kraken.ExchangeRates.Add(new PairRate(CurrencyPair.Parse("LTHN_BTC"), new BidAsk(0.1m)));
|
||||
rateProviderFactory.Providers.Add("kraken", kraken);
|
||||
}
|
||||
|
||||
await s.RegisterNewUser(true);
|
||||
await s.CreateNewStore(preferredExchange: "Kraken");
|
||||
await s.Page.Locator("a.nav-link[href*='zano/ZANO']").ClickAsync();
|
||||
await s.Page.Locator("a.nav-link[href*='lethean/LTHN']").ClickAsync();
|
||||
|
||||
// Enable Zano and configure settlement threshold
|
||||
// Enable Lethean and configure settlement threshold
|
||||
await s.Page.CheckAsync("#Enabled");
|
||||
await s.Page.SelectOptionAsync("#SettlementConfirmationThresholdChoice", "2");
|
||||
await s.Page.ClickAsync("#SaveButton");
|
||||
|
|
@ -46,7 +46,7 @@ public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoi
|
|||
// Set rate provider
|
||||
await s.Page.Locator("#menu-item-General").ClickAsync();
|
||||
await s.Page.Locator("#menu-item-Rates").ClickAsync();
|
||||
await s.Page.FillAsync("#DefaultCurrencyPairs", "BTC_USD,ZANO_USD,ZANO_BTC");
|
||||
await s.Page.FillAsync("#DefaultCurrencyPairs", "BTC_USD,LTHN_USD,LTHN_BTC");
|
||||
await s.Page.SelectOptionAsync("#PrimarySource_PreferredExchange", "kraken");
|
||||
await s.Page.Locator("#page-primary").ClickAsync();
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoi
|
|||
await s.Page.Locator("a.nav-link[href*='invoices']").ClickAsync();
|
||||
await s.Page.Locator("#page-primary").ClickAsync();
|
||||
await s.Page.FillAsync("#Amount", "4.20");
|
||||
await s.Page.FillAsync("#BuyerEmail", "zano@zano.org");
|
||||
await s.Page.FillAsync("#BuyerEmail", "lethean@lethean.org");
|
||||
await Task.Delay(TimeSpan.FromSeconds(25)); // wallet-rpc needs some time to sync
|
||||
await s.Page.Locator("#page-primary").ClickAsync();
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoi
|
|||
|
||||
// Select confirmation time to 0
|
||||
await s.Page.GoBackAsync();
|
||||
await s.Page.Locator("a.nav-link[href*='zano/ZANO']").ClickAsync();
|
||||
await s.Page.Locator("a.nav-link[href*='lethean/LTHN']").ClickAsync();
|
||||
await s.Page.SelectOptionAsync("#SettlementConfirmationThresholdChoice", "3");
|
||||
await s.Page.ClickAsync("#SaveButton");
|
||||
|
||||
|
|
@ -83,11 +83,11 @@ public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoi
|
|||
public async Task ShouldLoadWalletOnStartUpIfExists()
|
||||
{
|
||||
await using var s = CreatePlaywrightTester();
|
||||
await IntegrationTestUtils.CopyWalletFilesToZanoRpcDirAsync(s, "wallet");
|
||||
await IntegrationTestUtils.CopyWalletFilesToLetheanRpcDirAsync(s, "wallet");
|
||||
await s.StartAsync();
|
||||
await s.RegisterNewUser(true);
|
||||
await s.CreateNewStore();
|
||||
await s.Page.Locator("a.nav-link[href*='zano/ZANO']").ClickAsync();
|
||||
await s.Page.Locator("a.nav-link[href*='lethean/LTHN']").ClickAsync();
|
||||
|
||||
var walletRpcIsAvailable = await s.Page
|
||||
.Locator("li.list-group-item:text('Wallet RPC available: True')")
|
||||
|
|
@ -102,11 +102,11 @@ public class ZanoPluginIntegrationTest(ITestOutputHelper helper) : ZanoAndBitcoi
|
|||
public async Task ShouldLoadWalletWithPasswordOnStartUpIfExists()
|
||||
{
|
||||
await using var s = CreatePlaywrightTester();
|
||||
await IntegrationTestUtils.CopyWalletFilesToZanoRpcDirAsync(s, "wallet_password");
|
||||
await IntegrationTestUtils.CopyWalletFilesToLetheanRpcDirAsync(s, "wallet_password");
|
||||
await s.StartAsync();
|
||||
await s.RegisterNewUser(true);
|
||||
await s.CreateNewStore();
|
||||
await s.Page.Locator("a.nav-link[href*='zano/ZANO']").ClickAsync();
|
||||
await s.Page.Locator("a.nav-link[href*='lethean/LTHN']").ClickAsync();
|
||||
|
||||
var walletRpcIsAvailable = await s.Page
|
||||
.Locator("li.list-group-item:text('Wallet RPC available: True')")
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
using BTCPayServer.Tests;
|
||||
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace BTCPayServer.Plugins.IntegrationTests.Zano
|
||||
{
|
||||
public class ZanoAndBitcoinIntegrationTestBase : UnitTestBase
|
||||
{
|
||||
|
||||
public ZanoAndBitcoinIntegrationTestBase(ITestOutputHelper helper) : base(helper)
|
||||
{
|
||||
SetDefaultEnv("BTCPAY_ZANO_DAEMON_URI", "http://127.0.0.1:11211");
|
||||
SetDefaultEnv("BTCPAY_ZANO_WALLET_DAEMON_URI", "http://127.0.0.1:11212");
|
||||
SetDefaultEnv("BTCPAY_ZANO_WALLET_DAEMON_WALLETDIR", "/wallet");
|
||||
}
|
||||
|
||||
private static void SetDefaultEnv(string key, string defaultValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(key)))
|
||||
{
|
||||
Environment.SetEnvironmentVariable(key, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,18 +11,18 @@ services:
|
|||
TESTS_EXPLORER_POSTGRES: User ID=postgres;Include Error Detail=true;Host=postgres;Port=5432;Database=nbxplorer
|
||||
TESTS_HOSTNAME: tests
|
||||
TESTS_INCONTAINER: "true"
|
||||
BTCPAY_ZANO_DAEMON_URI: http://37.27.100.59:10505
|
||||
BTCPAY_ZANO_WALLET_DAEMON_URI: http://zano_wallet:11212
|
||||
BTCPAY_ZANO_WALLET_DAEMON_WALLETDIR: /wallet
|
||||
BTCPAY_LTHN_DAEMON_URI: http://127.0.0.1:46941
|
||||
BTCPAY_LTHN_WALLET_DAEMON_URI: http://lethean_wallet:46944
|
||||
BTCPAY_LTHN_WALLET_DAEMON_WALLETDIR: /wallet
|
||||
depends_on:
|
||||
- nbxplorer
|
||||
- postgres
|
||||
- zano_wallet
|
||||
- lethean_wallet
|
||||
extra_hosts:
|
||||
- "tests:127.0.0.1"
|
||||
volumes:
|
||||
- ../coverage:/coverage
|
||||
- zano_wallet:/wallet
|
||||
- lethean_wallet:/wallet
|
||||
|
||||
# The dev container is not used, it is just handy to run `docker-compose up dev` to start all services
|
||||
dev:
|
||||
|
|
@ -32,7 +32,7 @@ services:
|
|||
depends_on:
|
||||
- nbxplorer
|
||||
- postgres
|
||||
- zano_wallet
|
||||
- lethean_wallet
|
||||
|
||||
nbxplorer:
|
||||
image: nicolasdorier/nbxplorer:2.5.25
|
||||
|
|
@ -89,40 +89,40 @@ services:
|
|||
volumes:
|
||||
- "bitcoin_datadir:/data"
|
||||
|
||||
zanod:
|
||||
image: pavelravaga/zano:2.2.0.455
|
||||
letheand:
|
||||
image: letheanio/letheand:latest
|
||||
restart: unless-stopped
|
||||
container_name: zanod
|
||||
entrypoint: zanod
|
||||
container_name: letheand
|
||||
entrypoint: letheand
|
||||
command: >
|
||||
--rpc-bind-ip=0.0.0.0
|
||||
--rpc-bind-port=11211
|
||||
--rpc-bind-port=46941
|
||||
--log-level=2
|
||||
--data-dir=/data
|
||||
volumes:
|
||||
- zano_data:/data
|
||||
- lethean_data:/data
|
||||
ports:
|
||||
- "11211:11211"
|
||||
- "46941:46941"
|
||||
|
||||
zano_wallet:
|
||||
image: pavelravaga/zano:2.2.0.455
|
||||
lethean_wallet:
|
||||
image: letheanio/letheand:latest
|
||||
restart: unless-stopped
|
||||
container_name: zano_wallet
|
||||
container_name: lethean_wallet
|
||||
entrypoint: /bin/bash
|
||||
command:
|
||||
- -c
|
||||
- |
|
||||
if [ ! -f /wallet/wallet.keys ]; then
|
||||
echo "Generating new wallet..."
|
||||
echo "exit" | simplewallet --generate-new-wallet=/wallet/wallet --password pass --daemon-address=37.27.100.59:10505
|
||||
echo "exit" | simplewallet --generate-new-wallet=/wallet/wallet --password pass --daemon-address=127.0.0.1:46941
|
||||
fi
|
||||
simplewallet --wallet-file=/wallet/wallet --password pass --daemon-address=37.27.100.59:10505 --rpc-bind-ip=0.0.0.0 --rpc-bind-port=11212
|
||||
simplewallet --wallet-file=/wallet/wallet --password pass --daemon-address=127.0.0.1:46941 --rpc-bind-ip=0.0.0.0 --rpc-bind-port=46944
|
||||
ports:
|
||||
- "11212:11212"
|
||||
- "46944:46944"
|
||||
volumes:
|
||||
- zano_wallet:/wallet
|
||||
- lethean_wallet:/wallet
|
||||
depends_on:
|
||||
- zanod
|
||||
- letheand
|
||||
|
||||
postgres:
|
||||
image: postgres:17.4
|
||||
|
|
@ -136,8 +136,8 @@ services:
|
|||
|
||||
volumes:
|
||||
bitcoin_datadir:
|
||||
zano_data:
|
||||
zano_wallet:
|
||||
lethean_data:
|
||||
lethean_wallet:
|
||||
|
||||
networks:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Plugins\Zano\BTCPayServer.Plugins.Zano.csproj" />
|
||||
<ProjectReference Include="..\Plugins\Lethean\BTCPayServer.Plugins.Lethean.csproj" />
|
||||
<ProjectReference Include="..\submodules\btcpayserver\BTCPayServer.Abstractions\BTCPayServer.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Lethean.Configuration
|
||||
{
|
||||
public class LetheanConfigurationTests
|
||||
{
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LetheanConfiguration_ShouldInitializeWithEmptyDictionary()
|
||||
{
|
||||
var config = new LetheanConfiguration();
|
||||
|
||||
Assert.NotNull(config.LetheanConfigurationItems);
|
||||
Assert.Empty(config.LetheanConfigurationItems);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LetheanConfigurationItem_ShouldSetAndGetProperties()
|
||||
{
|
||||
var configItem = new LetheanConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:36941"),
|
||||
InternalWalletRpcUri = new Uri("http://localhost:36944"),
|
||||
WalletDirectory = "/wallets"
|
||||
};
|
||||
|
||||
Assert.Equal("http://localhost:36941/", configItem.DaemonRpcUri.ToString());
|
||||
Assert.Equal("http://localhost:36944/", configItem.InternalWalletRpcUri.ToString());
|
||||
Assert.Equal("/wallets", configItem.WalletDirectory);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LetheanConfiguration_ShouldAddAndRetrieveItems()
|
||||
{
|
||||
var config = new LetheanConfiguration();
|
||||
var configItem = new LetheanConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:36941"),
|
||||
InternalWalletRpcUri = new Uri("http://localhost:36944"),
|
||||
WalletDirectory = "/wallets"
|
||||
};
|
||||
|
||||
config.LetheanConfigurationItems.Add("LTHN", configItem);
|
||||
|
||||
Assert.Single(config.LetheanConfigurationItems);
|
||||
Assert.True(config.LetheanConfigurationItems.ContainsKey("LTHN"));
|
||||
Assert.Equal(configItem, config.LetheanConfigurationItems["LTHN"]);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LetheanConfiguration_ShouldHandleDuplicateKeys()
|
||||
{
|
||||
var config = new LetheanConfiguration();
|
||||
var configItem1 = new LetheanConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:36941")
|
||||
};
|
||||
var configItem2 = new LetheanConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:36944")
|
||||
};
|
||||
|
||||
config.LetheanConfigurationItems.Add("LTHN", configItem1);
|
||||
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
config.LetheanConfigurationItems.Add("LTHN", configItem2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
using BTCPayServer.Plugins.Zano.Payments;
|
||||
using BTCPayServer.Plugins.Lethean.Payments;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Zano.Payments
|
||||
namespace BTCPayServer.Plugins.UnitTests.Lethean.Payments
|
||||
{
|
||||
public class ZanoPaymentDataTests
|
||||
public class LetheanPaymentDataTests
|
||||
{
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void DefaultValues_ShouldBeCorrect()
|
||||
{
|
||||
var paymentData = new ZanoPaymentData();
|
||||
var paymentData = new LetheanPaymentData();
|
||||
|
||||
Assert.Null(paymentData.PaymentId);
|
||||
Assert.Equal(0, paymentData.BlockHeight);
|
||||
|
|
@ -24,7 +24,7 @@ namespace BTCPayServer.Plugins.UnitTests.Zano.Payments
|
|||
[Fact]
|
||||
public void Properties_ShouldBeSettable()
|
||||
{
|
||||
var paymentData = new ZanoPaymentData();
|
||||
var paymentData = new LetheanPaymentData();
|
||||
|
||||
paymentData.PaymentId = "abcdef0123456789";
|
||||
paymentData.BlockHeight = 100;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using BTCPayServer.Plugins.Lethean.RPC;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Lethean.RPC
|
||||
{
|
||||
public class LetheanPollEventTest
|
||||
{
|
||||
[Fact]
|
||||
public void DefaultInitialization_ShouldHaveNullCryptoCode()
|
||||
{
|
||||
var pollEvent = new LetheanPollEvent();
|
||||
|
||||
Assert.Null(pollEvent.CryptoCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PropertyAssignment_ShouldSetAndRetrieveValues()
|
||||
{
|
||||
var pollEvent = new LetheanPollEvent
|
||||
{
|
||||
CryptoCode = "LTHN"
|
||||
};
|
||||
|
||||
Assert.Equal("LTHN", pollEvent.CryptoCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
using BTCPayServer.Plugins.Zano.RPC.Models;
|
||||
using BTCPayServer.Plugins.Lethean.RPC.Models;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.UnitTests.Lethean.RPC.Models
|
||||
{
|
||||
public class ParseStringConverterTests
|
||||
{
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
using System.Globalization;
|
||||
|
||||
using BTCPayServer.Plugins.Zano.Utils;
|
||||
using BTCPayServer.Plugins.Lethean.Utils;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Zano.Utils
|
||||
namespace BTCPayServer.Plugins.UnitTests.Lethean.Utils
|
||||
{
|
||||
public class ZanoMoneyTests
|
||||
public class LetheanMoneyTests
|
||||
{
|
||||
[Trait("Category", "Unit")]
|
||||
[Theory]
|
||||
|
|
@ -16,7 +16,7 @@ namespace BTCPayServer.Plugins.UnitTests.Zano.Utils
|
|||
public void Convert_LongToDecimal_ReturnsExpectedValue(long atomicUnits, string expectedString)
|
||||
{
|
||||
decimal expected = decimal.Parse(expectedString, CultureInfo.InvariantCulture);
|
||||
decimal result = ZanoMoney.Convert(atomicUnits);
|
||||
decimal result = LetheanMoney.Convert(atomicUnits);
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
|
|
@ -25,10 +25,10 @@ namespace BTCPayServer.Plugins.UnitTests.Zano.Utils
|
|||
[InlineData("0.000000000001", 1)]
|
||||
[InlineData("0.123456789012", 123456789012)]
|
||||
[InlineData("1.000000000000", 1000000000000)]
|
||||
public void Convert_DecimalToLong_ReturnsExpectedValue(string zanoString, long expectedAtomicUnits)
|
||||
public void Convert_DecimalToLong_ReturnsExpectedValue(string letheanString, long expectedAtomicUnits)
|
||||
{
|
||||
decimal zano = decimal.Parse(zanoString, CultureInfo.InvariantCulture);
|
||||
long result = ZanoMoney.Convert(zano);
|
||||
decimal lethean = decimal.Parse(letheanString, CultureInfo.InvariantCulture);
|
||||
long result = LetheanMoney.Convert(lethean);
|
||||
Assert.Equal(expectedAtomicUnits, result);
|
||||
}
|
||||
|
||||
|
|
@ -39,8 +39,8 @@ namespace BTCPayServer.Plugins.UnitTests.Zano.Utils
|
|||
[InlineData(1000000000000)]
|
||||
public void RoundTripConversion_LongToDecimalToLong_ReturnsOriginalValue(long atomicUnits)
|
||||
{
|
||||
decimal zano = ZanoMoney.Convert(atomicUnits);
|
||||
long convertedBack = ZanoMoney.Convert(zano);
|
||||
decimal lethean = LetheanMoney.Convert(atomicUnits);
|
||||
long convertedBack = LetheanMoney.Convert(lethean);
|
||||
Assert.Equal(atomicUnits, convertedBack);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,27 @@
|
|||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Plugins.Zano.ViewModels;
|
||||
using BTCPayServer.Plugins.Lethean.ViewModels;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Zano.ViewModels
|
||||
namespace BTCPayServer.Plugins.UnitTests.Lethean.ViewModels
|
||||
{
|
||||
public class ZanoPaymentViewModelTests
|
||||
public class LetheanPaymentViewModelTests
|
||||
{
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ZanoPaymentViewModel_SetGetProperties_ReturnsCorrectValues()
|
||||
public void LetheanPaymentViewModel_SetGetProperties_ReturnsCorrectValues()
|
||||
{
|
||||
var viewModel = new ZanoPaymentViewModel();
|
||||
var viewModel = new LetheanPaymentViewModel();
|
||||
|
||||
var paymentMethodId = new PaymentMethodId("ZANO");
|
||||
var paymentMethodId = new PaymentMethodId("LTHN");
|
||||
|
||||
var confirmations = "3";
|
||||
var depositAddress = "zanoaddress";
|
||||
var depositAddress = "letheanaddress";
|
||||
var amount = "100.5";
|
||||
var transactionId = "tx123";
|
||||
var receivedTime = DateTimeOffset.UtcNow;
|
||||
var transactionLink = "https://explorer.zano.com/tx/tx123";
|
||||
var currency = "ZANO";
|
||||
var transactionLink = "https://explorer.lethean.com/tx/tx123";
|
||||
var currency = "LTHN";
|
||||
|
||||
viewModel.PaymentMethodId = paymentMethodId;
|
||||
viewModel.Confirmations = confirmations;
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
using System;
|
||||
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Zano.Configuration
|
||||
{
|
||||
public class ZanoConfigurationTests
|
||||
{
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ZanoConfiguration_ShouldInitializeWithEmptyDictionary()
|
||||
{
|
||||
var config = new ZanoConfiguration();
|
||||
|
||||
Assert.NotNull(config.ZanoConfigurationItems);
|
||||
Assert.Empty(config.ZanoConfigurationItems);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ZanoConfigurationItem_ShouldSetAndGetProperties()
|
||||
{
|
||||
var configItem = new ZanoConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:11211"),
|
||||
InternalWalletRpcUri = new Uri("http://localhost:11212"),
|
||||
WalletDirectory = "/wallets"
|
||||
};
|
||||
|
||||
Assert.Equal("http://localhost:11211/", configItem.DaemonRpcUri.ToString());
|
||||
Assert.Equal("http://localhost:11212/", configItem.InternalWalletRpcUri.ToString());
|
||||
Assert.Equal("/wallets", configItem.WalletDirectory);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ZanoConfiguration_ShouldAddAndRetrieveItems()
|
||||
{
|
||||
var config = new ZanoConfiguration();
|
||||
var configItem = new ZanoConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:11211"),
|
||||
InternalWalletRpcUri = new Uri("http://localhost:11212"),
|
||||
WalletDirectory = "/wallets"
|
||||
};
|
||||
|
||||
config.ZanoConfigurationItems.Add("ZANO", configItem);
|
||||
|
||||
Assert.Single(config.ZanoConfigurationItems);
|
||||
Assert.True(config.ZanoConfigurationItems.ContainsKey("ZANO"));
|
||||
Assert.Equal(configItem, config.ZanoConfigurationItems["ZANO"]);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ZanoConfiguration_ShouldHandleDuplicateKeys()
|
||||
{
|
||||
var config = new ZanoConfiguration();
|
||||
var configItem1 = new ZanoConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:11211")
|
||||
};
|
||||
var configItem2 = new ZanoConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = new Uri("http://localhost:11212")
|
||||
};
|
||||
|
||||
config.ZanoConfigurationItems.Add("ZANO", configItem1);
|
||||
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
config.ZanoConfigurationItems.Add("ZANO", configItem2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
using BTCPayServer.Plugins.Zano.RPC;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Plugins.UnitTests.Zano.RPC
|
||||
{
|
||||
public class ZanoPollEventTest
|
||||
{
|
||||
[Fact]
|
||||
public void DefaultInitialization_ShouldHaveNullCryptoCode()
|
||||
{
|
||||
var pollEvent = new ZanoPollEvent();
|
||||
|
||||
Assert.Null(pollEvent.CryptoCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PropertyAssignment_ShouldSetAndRetrieveValues()
|
||||
{
|
||||
var pollEvent = new ZanoPollEvent
|
||||
{
|
||||
CryptoCode = "ZANO"
|
||||
};
|
||||
|
||||
Assert.Equal("ZANO", pollEvent.CryptoCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
We follow the [Ruby Community's Code of Conduct](https://www.ruby-lang.org/en/conduct/) to ensure a safe, respectful, and productive environment for all participants.
|
||||
|
||||
If you experience or witness any violations of this Code of Conduct, please reach out to us in our [Matrix room](https://matrix.to/#/#btcpay-zano:matrix.org) so we can address the issue promptly.
|
||||
If you experience or witness any violations of this Code of Conduct, please reach out to us in our [Matrix room](https://matrix.to/#/#btcpay-lethean:matrix.org) so we can address the issue promptly.
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
<!-- Plugin specific properties -->
|
||||
<PropertyGroup>
|
||||
<Product>Zano</Product>
|
||||
<Description>This plugin extends BTCPay Server to enable users to receive payments via Zano.</Description>
|
||||
<Product>Lethean</Product>
|
||||
<Description>This plugin extends BTCPay Server to enable users to receive payments via Lethean.</Description>
|
||||
<Version>1.0.0</Version>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
</PropertyGroup>
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
-->
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="BTCPayServer.Plugins.Zano.json">
|
||||
<None Update="BTCPayServer.Plugins.Lethean.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
|
@ -75,6 +75,6 @@
|
|||
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="zano.svg" />
|
||||
<EmbeddedResource Include="lethean.svg" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
17
Plugins/Lethean/BTCPayServer.Plugins.Lethean.json
Normal file
17
Plugins/Lethean/BTCPayServer.Plugins.Lethean.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"Identifier": "BTCPayServer.Plugins.Lethean",
|
||||
"Name": "Lethean",
|
||||
"Version": "1.0.0",
|
||||
"Description": "Accept Lethean (LTHN) payments in BTCPay Server. Privacy-focused cryptocurrency with confidential transactions.",
|
||||
"SystemPlugin": false,
|
||||
"Dependencies": [
|
||||
{
|
||||
"Identifier": "BTCPayServer",
|
||||
"Condition": ">=2.1.0"
|
||||
}
|
||||
],
|
||||
"Documentation": "https://github.com/lethean-io/btcpayserver-lethean-plugin",
|
||||
"Source": "https://github.com/lethean-io/btcpayserver-lethean-plugin",
|
||||
"Author": "Lethean",
|
||||
"AuthorLink": "https://lethean.io"
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.Zano", "BTCPayServer.Plugins.Zano.csproj", "{440E70AD-BA40-449C-8315-6A13D95B6ED7}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.Lethean", "BTCPayServer.Plugins.Lethean.csproj", "{440E70AD-BA40-449C-8315-6A13D95B6ED7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
17
Plugins/Lethean/Configuration/LetheanConfiguration.cs
Normal file
17
Plugins/Lethean/Configuration/LetheanConfiguration.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Plugins.Lethean.Configuration
|
||||
{
|
||||
public class LetheanConfiguration
|
||||
{
|
||||
public Dictionary<string, LetheanConfigurationItem> LetheanConfigurationItems { get; set; } = [];
|
||||
}
|
||||
|
||||
public class LetheanConfigurationItem
|
||||
{
|
||||
public Uri DaemonRpcUri { get; set; }
|
||||
public Uri InternalWalletRpcUri { get; set; }
|
||||
public string WalletDirectory { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,9 @@ using BTCPayServer.Abstractions.Constants;
|
|||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
using BTCPayServer.Plugins.Zano.Payments;
|
||||
using BTCPayServer.Plugins.Zano.Services;
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
using BTCPayServer.Plugins.Lethean.Payments;
|
||||
using BTCPayServer.Plugins.Lethean.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
|
||||
|
|
@ -18,58 +18,58 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Controllers
|
||||
namespace BTCPayServer.Plugins.Lethean.Controllers
|
||||
{
|
||||
[Route("stores/{storeId}/zano")]
|
||||
[Route("stores/{storeId}/lethean")]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[Authorize(Policy = Policies.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public class UIZanoStoreController : Controller
|
||||
public class UILetheanStoreController : Controller
|
||||
{
|
||||
private readonly ZanoConfiguration _zanoConfiguration;
|
||||
private readonly LetheanConfiguration _letheanConfiguration;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly ZanoRpcProvider _zanoRpcProvider;
|
||||
private readonly LetheanRpcProvider _letheanRpcProvider;
|
||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public UIZanoStoreController(ZanoConfiguration zanoConfiguration,
|
||||
StoreRepository storeRepository, ZanoRpcProvider zanoRpcProvider,
|
||||
public UILetheanStoreController(LetheanConfiguration letheanConfiguration,
|
||||
StoreRepository storeRepository, LetheanRpcProvider letheanRpcProvider,
|
||||
PaymentMethodHandlerDictionary handlers,
|
||||
IStringLocalizer stringLocalizer)
|
||||
{
|
||||
_zanoConfiguration = zanoConfiguration;
|
||||
_letheanConfiguration = letheanConfiguration;
|
||||
_storeRepository = storeRepository;
|
||||
_zanoRpcProvider = zanoRpcProvider;
|
||||
_letheanRpcProvider = letheanRpcProvider;
|
||||
_handlers = handlers;
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public StoreData StoreData => HttpContext.GetStoreData();
|
||||
|
||||
private ZanoPaymentMethodViewModel GetZanoPaymentMethodViewModel(
|
||||
private LetheanPaymentMethodViewModel GetLetheanPaymentMethodViewModel(
|
||||
StoreData storeData, string cryptoCode,
|
||||
IPaymentFilter excludeFilters)
|
||||
{
|
||||
var zano = storeData.GetPaymentMethodConfigs(_handlers)
|
||||
.Where(s => s.Value is ZanoPaymentPromptDetails)
|
||||
.Select(s => (PaymentMethodId: s.Key, Details: (ZanoPaymentPromptDetails)s.Value));
|
||||
var lethean = storeData.GetPaymentMethodConfigs(_handlers)
|
||||
.Where(s => s.Value is LetheanPaymentPromptDetails)
|
||||
.Select(s => (PaymentMethodId: s.Key, Details: (LetheanPaymentPromptDetails)s.Value));
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode);
|
||||
var settings = zano.Where(method => method.PaymentMethodId == pmi).Select(m => m.Details).SingleOrDefault();
|
||||
_zanoRpcProvider.Summaries.TryGetValue(cryptoCode, out var summary);
|
||||
var settings = lethean.Where(method => method.PaymentMethodId == pmi).Select(m => m.Details).SingleOrDefault();
|
||||
_letheanRpcProvider.Summaries.TryGetValue(cryptoCode, out var summary);
|
||||
|
||||
var settlementThresholdChoice = ZanoSettlementThresholdChoice.StoreSpeedPolicy;
|
||||
var settlementThresholdChoice = LetheanSettlementThresholdChoice.StoreSpeedPolicy;
|
||||
if (settings != null && settings.InvoiceSettledConfirmationThreshold is { } confirmations)
|
||||
{
|
||||
settlementThresholdChoice = confirmations switch
|
||||
{
|
||||
0 => ZanoSettlementThresholdChoice.ZeroConfirmation,
|
||||
1 => ZanoSettlementThresholdChoice.AtLeastOne,
|
||||
10 => ZanoSettlementThresholdChoice.AtLeastTen,
|
||||
_ => ZanoSettlementThresholdChoice.Custom
|
||||
0 => LetheanSettlementThresholdChoice.ZeroConfirmation,
|
||||
1 => LetheanSettlementThresholdChoice.AtLeastOne,
|
||||
10 => LetheanSettlementThresholdChoice.AtLeastTen,
|
||||
_ => LetheanSettlementThresholdChoice.Custom
|
||||
};
|
||||
}
|
||||
|
||||
return new ZanoPaymentMethodViewModel()
|
||||
return new LetheanPaymentMethodViewModel()
|
||||
{
|
||||
Enabled =
|
||||
settings != null &&
|
||||
|
|
@ -79,32 +79,32 @@ namespace BTCPayServer.Plugins.Zano.Controllers
|
|||
SettlementConfirmationThresholdChoice = settlementThresholdChoice,
|
||||
CustomSettlementConfirmationThreshold =
|
||||
settings != null &&
|
||||
settlementThresholdChoice is ZanoSettlementThresholdChoice.Custom
|
||||
settlementThresholdChoice is LetheanSettlementThresholdChoice.Custom
|
||||
? settings.InvoiceSettledConfirmationThreshold
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("{cryptoCode}")]
|
||||
public IActionResult GetStoreZanoPaymentMethod(string cryptoCode)
|
||||
public IActionResult GetStoreLetheanPaymentMethod(string cryptoCode)
|
||||
{
|
||||
cryptoCode = cryptoCode.ToUpperInvariant();
|
||||
if (!_zanoConfiguration.ZanoConfigurationItems.ContainsKey(cryptoCode))
|
||||
if (!_letheanConfiguration.LetheanConfigurationItems.ContainsKey(cryptoCode))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var vm = GetZanoPaymentMethodViewModel(StoreData, cryptoCode,
|
||||
var vm = GetLetheanPaymentMethodViewModel(StoreData, cryptoCode,
|
||||
StoreData.GetStoreBlob().GetExcludedPaymentMethods());
|
||||
return View("/Views/Zano/GetStoreZanoPaymentMethod.cshtml", vm);
|
||||
return View("/Views/Lethean/GetStoreLetheanPaymentMethod.cshtml", vm);
|
||||
}
|
||||
|
||||
[HttpPost("{cryptoCode}")]
|
||||
[DisableRequestSizeLimit]
|
||||
public async Task<IActionResult> GetStoreZanoPaymentMethod(ZanoPaymentMethodViewModel viewModel, string cryptoCode)
|
||||
public async Task<IActionResult> GetStoreLetheanPaymentMethod(LetheanPaymentMethodViewModel viewModel, string cryptoCode)
|
||||
{
|
||||
cryptoCode = cryptoCode.ToUpperInvariant();
|
||||
if (!_zanoConfiguration.ZanoConfigurationItems.TryGetValue(cryptoCode,
|
||||
if (!_letheanConfiguration.LetheanConfigurationItems.TryGetValue(cryptoCode,
|
||||
out _))
|
||||
{
|
||||
return NotFound();
|
||||
|
|
@ -112,24 +112,24 @@ namespace BTCPayServer.Plugins.Zano.Controllers
|
|||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var vm = GetZanoPaymentMethodViewModel(StoreData, cryptoCode,
|
||||
var vm = GetLetheanPaymentMethodViewModel(StoreData, cryptoCode,
|
||||
StoreData.GetStoreBlob().GetExcludedPaymentMethods());
|
||||
vm.Enabled = viewModel.Enabled;
|
||||
vm.SettlementConfirmationThresholdChoice = viewModel.SettlementConfirmationThresholdChoice;
|
||||
vm.CustomSettlementConfirmationThreshold = viewModel.CustomSettlementConfirmationThreshold;
|
||||
return View("/Views/Zano/GetStoreZanoPaymentMethod.cshtml", vm);
|
||||
return View("/Views/Lethean/GetStoreLetheanPaymentMethod.cshtml", vm);
|
||||
}
|
||||
|
||||
var storeData = StoreData;
|
||||
var blob = storeData.GetStoreBlob();
|
||||
storeData.SetPaymentMethodConfig(_handlers[PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode)], new ZanoPaymentPromptDetails()
|
||||
storeData.SetPaymentMethodConfig(_handlers[PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode)], new LetheanPaymentPromptDetails()
|
||||
{
|
||||
InvoiceSettledConfirmationThreshold = viewModel.SettlementConfirmationThresholdChoice switch
|
||||
{
|
||||
ZanoSettlementThresholdChoice.ZeroConfirmation => 0,
|
||||
ZanoSettlementThresholdChoice.AtLeastOne => 1,
|
||||
ZanoSettlementThresholdChoice.AtLeastTen => 10,
|
||||
ZanoSettlementThresholdChoice.Custom when viewModel.CustomSettlementConfirmationThreshold is { } custom => custom,
|
||||
LetheanSettlementThresholdChoice.ZeroConfirmation => 0,
|
||||
LetheanSettlementThresholdChoice.AtLeastOne => 1,
|
||||
LetheanSettlementThresholdChoice.AtLeastTen => 10,
|
||||
LetheanSettlementThresholdChoice.Custom when viewModel.CustomSettlementConfirmationThreshold is { } custom => custom,
|
||||
_ => null
|
||||
}
|
||||
});
|
||||
|
|
@ -137,23 +137,23 @@ namespace BTCPayServer.Plugins.Zano.Controllers
|
|||
blob.SetExcluded(PaymentTypes.CHAIN.GetPaymentMethodId(viewModel.CryptoCode), !viewModel.Enabled);
|
||||
storeData.SetStoreBlob(blob);
|
||||
await _storeRepository.UpdateStore(storeData);
|
||||
return RedirectToAction("GetStoreZanoPaymentMethod", new { cryptoCode });
|
||||
return RedirectToAction("GetStoreLetheanPaymentMethod", new { cryptoCode });
|
||||
}
|
||||
|
||||
public class ZanoPaymentMethodViewModel : IValidatableObject
|
||||
public class LetheanPaymentMethodViewModel : IValidatableObject
|
||||
{
|
||||
public ZanoRpcProvider.ZanoSummary Summary { get; set; }
|
||||
public LetheanRpcProvider.LetheanSummary Summary { get; set; }
|
||||
public string CryptoCode { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[Display(Name = "Consider the invoice settled when the payment transaction ...")]
|
||||
public ZanoSettlementThresholdChoice SettlementConfirmationThresholdChoice { get; set; }
|
||||
public LetheanSettlementThresholdChoice SettlementConfirmationThresholdChoice { get; set; }
|
||||
[Display(Name = "Required Confirmations"), Range(0, 100)]
|
||||
public long? CustomSettlementConfirmationThreshold { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (SettlementConfirmationThresholdChoice is ZanoSettlementThresholdChoice.Custom
|
||||
if (SettlementConfirmationThresholdChoice is LetheanSettlementThresholdChoice.Custom
|
||||
&& CustomSettlementConfirmationThreshold is null)
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
|
|
@ -163,7 +163,7 @@ namespace BTCPayServer.Plugins.Zano.Controllers
|
|||
}
|
||||
}
|
||||
|
||||
public enum ZanoSettlementThresholdChoice
|
||||
public enum LetheanSettlementThresholdChoice
|
||||
{
|
||||
[Display(Name = "Store Speed Policy", Description = "Use the store's speed policy")]
|
||||
StoreSpeedPolicy,
|
||||
|
|
@ -7,9 +7,9 @@ using BTCPayServer.Abstractions.Models;
|
|||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Hosting;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
using BTCPayServer.Plugins.Zano.Payments;
|
||||
using BTCPayServer.Plugins.Zano.Services;
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
using BTCPayServer.Plugins.Lethean.Payments;
|
||||
using BTCPayServer.Plugins.Lethean.Services;
|
||||
using BTCPayServer.Services;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
|
@ -20,9 +20,9 @@ using NBitcoin;
|
|||
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano;
|
||||
namespace BTCPayServer.Plugins.Lethean;
|
||||
|
||||
public class ZanoPlugin : BaseBTCPayServerPlugin
|
||||
public class LetheanPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||
{
|
||||
|
|
@ -35,44 +35,44 @@ public class ZanoPlugin : BaseBTCPayServerPlugin
|
|||
var prov = pluginServices.BootstrapServices.GetRequiredService<NBXplorerNetworkProvider>();
|
||||
var chainName = prov.NetworkType;
|
||||
|
||||
var network = new ZanoSpecificBtcPayNetwork()
|
||||
var network = new LetheanSpecificBtcPayNetwork()
|
||||
{
|
||||
CryptoCode = "ZANO",
|
||||
DisplayName = "Zano",
|
||||
CryptoCode = "LTHN",
|
||||
DisplayName = "Lethean",
|
||||
Divisibility = 12,
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"ZANO_X = ZANO_BTC * BTC_X",
|
||||
"ZANO_BTC = coingecko(ZANO_BTC)"
|
||||
"LTHN_X = LTHN_BTC * BTC_X",
|
||||
"LTHN_BTC = coingecko(LTHN_BTC)"
|
||||
},
|
||||
CryptoImagePath = "zano.svg",
|
||||
UriScheme = "zano"
|
||||
CryptoImagePath = "lethean.svg",
|
||||
UriScheme = "lethean"
|
||||
};
|
||||
var blockExplorerLink = chainName == ChainName.Mainnet
|
||||
? "https://explorer.zano.org/transaction/{0}"
|
||||
: "https://testnet-explorer.zano.org/transaction/{0}";
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("ZANO");
|
||||
? "https://explorer.lethean.org/transaction/{0}"
|
||||
: "https://testnet-explorer.lethean.org/transaction/{0}";
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("LTHN");
|
||||
services.AddDefaultPrettyName(pmi, network.DisplayName);
|
||||
services.AddBTCPayNetwork(network)
|
||||
.AddTransactionLinkProvider(pmi, new SimpleTransactionLinkProvider(blockExplorerLink));
|
||||
|
||||
services.AddSingleton(provider =>
|
||||
ConfigureZanoConfiguration(provider));
|
||||
services.AddHttpClient("ZanoClient");
|
||||
services.AddSingleton<ZanoRpcProvider>();
|
||||
services.AddHostedService<ZanoSummaryUpdaterHostedService>();
|
||||
services.AddHostedService<ZanoListener>();
|
||||
services.AddHostedService<ZanoLoadUpService>();
|
||||
ConfigureLetheanConfiguration(provider));
|
||||
services.AddHttpClient("LetheanClient");
|
||||
services.AddSingleton<LetheanRpcProvider>();
|
||||
services.AddHostedService<LetheanSummaryUpdaterHostedService>();
|
||||
services.AddHostedService<LetheanListener>();
|
||||
services.AddHostedService<LetheanLoadUpService>();
|
||||
services.AddSingleton(provider =>
|
||||
(IPaymentMethodHandler)ActivatorUtilities.CreateInstance(provider, typeof(ZanoPaymentMethodHandler), network));
|
||||
(IPaymentMethodHandler)ActivatorUtilities.CreateInstance(provider, typeof(LetheanPaymentMethodHandler), network));
|
||||
services.AddSingleton(provider =>
|
||||
(IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(ZanoPaymentLinkExtension), network, pmi));
|
||||
(IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(LetheanPaymentLinkExtension), network, pmi));
|
||||
services.AddSingleton(provider =>
|
||||
(ICheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(ZanoCheckoutModelExtension), network, pmi));
|
||||
(ICheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(LetheanCheckoutModelExtension), network, pmi));
|
||||
|
||||
services.AddUIExtension("store-wallets-nav", "/Views/Zano/StoreWalletsNavZanoExtension.cshtml");
|
||||
services.AddUIExtension("store-invoices-payments", "/Views/Zano/ViewZanoPaymentData.cshtml");
|
||||
services.AddSingleton<ISyncSummaryProvider, ZanoSyncSummaryProvider>();
|
||||
services.AddUIExtension("store-wallets-nav", "/Views/Lethean/StoreWalletsNavLetheanExtension.cshtml");
|
||||
services.AddUIExtension("store-invoices-payments", "/Views/Lethean/ViewLetheanPaymentData.cshtml");
|
||||
services.AddSingleton<ISyncSummaryProvider, LetheanSyncSummaryProvider>();
|
||||
}
|
||||
class SimpleTransactionLinkProvider : DefaultTransactionLinkProvider
|
||||
{
|
||||
|
|
@ -90,30 +90,30 @@ public class ZanoPlugin : BaseBTCPayServerPlugin
|
|||
}
|
||||
}
|
||||
|
||||
private static ZanoConfiguration ConfigureZanoConfiguration(IServiceProvider serviceProvider)
|
||||
private static LetheanConfiguration ConfigureLetheanConfiguration(IServiceProvider serviceProvider)
|
||||
{
|
||||
var configuration = serviceProvider.GetService<IConfiguration>();
|
||||
var btcPayNetworkProvider = serviceProvider.GetService<BTCPayNetworkProvider>();
|
||||
var result = new ZanoConfiguration();
|
||||
var result = new LetheanConfiguration();
|
||||
|
||||
var supportedNetworks = btcPayNetworkProvider.GetAll()
|
||||
.OfType<ZanoSpecificBtcPayNetwork>();
|
||||
.OfType<LetheanSpecificBtcPayNetwork>();
|
||||
|
||||
foreach (var zanoNetwork in supportedNetworks)
|
||||
foreach (var letheanNetwork in supportedNetworks)
|
||||
{
|
||||
var daemonUri =
|
||||
configuration.GetOrDefault<Uri>($"{zanoNetwork.CryptoCode}_daemon_uri",
|
||||
configuration.GetOrDefault<Uri>($"{letheanNetwork.CryptoCode}_daemon_uri",
|
||||
null);
|
||||
var walletDaemonUri =
|
||||
configuration.GetOrDefault<Uri>(
|
||||
$"{zanoNetwork.CryptoCode}_wallet_daemon_uri", null);
|
||||
$"{letheanNetwork.CryptoCode}_wallet_daemon_uri", null);
|
||||
var walletDaemonWalletDirectory =
|
||||
configuration.GetOrDefault<string>(
|
||||
$"{zanoNetwork.CryptoCode}_wallet_daemon_walletdir", null);
|
||||
$"{letheanNetwork.CryptoCode}_wallet_daemon_walletdir", null);
|
||||
if (daemonUri == null || walletDaemonUri == null)
|
||||
{
|
||||
var logger = serviceProvider.GetRequiredService<ILogger<ZanoPlugin>>();
|
||||
var cryptoCode = zanoNetwork.CryptoCode.ToUpperInvariant();
|
||||
var logger = serviceProvider.GetRequiredService<ILogger<LetheanPlugin>>();
|
||||
var cryptoCode = letheanNetwork.CryptoCode.ToUpperInvariant();
|
||||
if (daemonUri is null)
|
||||
{
|
||||
logger.LogWarning("BTCPAY_{CryptoCode}_DAEMON_URI is not configured", cryptoCode);
|
||||
|
|
@ -126,7 +126,7 @@ public class ZanoPlugin : BaseBTCPayServerPlugin
|
|||
}
|
||||
else
|
||||
{
|
||||
result.ZanoConfigurationItems.Add(zanoNetwork.CryptoCode, new ZanoConfigurationItem
|
||||
result.LetheanConfigurationItems.Add(letheanNetwork.CryptoCode, new LetheanConfigurationItem
|
||||
{
|
||||
DaemonRpcUri = daemonUri,
|
||||
InternalWalletRpcUri = walletDaemonUri,
|
||||
7
Plugins/Lethean/LetheanSpecificBtcPayNetwork.cs
Normal file
7
Plugins/Lethean/LetheanSpecificBtcPayNetwork.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace BTCPayServer.Plugins.Lethean;
|
||||
|
||||
public class LetheanSpecificBtcPayNetwork : BTCPayNetworkBase
|
||||
{
|
||||
public int MaxTrackedConfirmation = 10;
|
||||
public string UriScheme { get; set; }
|
||||
}
|
||||
|
|
@ -3,18 +3,18 @@ using System.Linq;
|
|||
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Plugins.Zano.Services;
|
||||
using BTCPayServer.Plugins.Lethean.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Payments
|
||||
namespace BTCPayServer.Plugins.Lethean.Payments
|
||||
{
|
||||
public class ZanoCheckoutModelExtension : ICheckoutModelExtension
|
||||
public class LetheanCheckoutModelExtension : ICheckoutModelExtension
|
||||
{
|
||||
private readonly BTCPayNetworkBase _network;
|
||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||
private readonly IPaymentLinkExtension paymentLinkExtension;
|
||||
|
||||
public ZanoCheckoutModelExtension(
|
||||
public LetheanCheckoutModelExtension(
|
||||
PaymentMethodId paymentMethodId,
|
||||
IEnumerable<IPaymentLinkExtension> paymentLinkExtensions,
|
||||
BTCPayNetworkBase network,
|
||||
|
|
@ -32,19 +32,19 @@ namespace BTCPayServer.Plugins.Zano.Payments
|
|||
|
||||
public void ModifyCheckoutModel(CheckoutModelContext context)
|
||||
{
|
||||
if (context is not { Handler: ZanoPaymentMethodHandler handler })
|
||||
if (context is not { Handler: LetheanPaymentMethodHandler handler })
|
||||
{
|
||||
return;
|
||||
}
|
||||
context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName;
|
||||
var details = context.InvoiceEntity.GetPayments(true)
|
||||
.Select(p => p.GetDetails<ZanoPaymentData>(handler))
|
||||
.Select(p => p.GetDetails<LetheanPaymentData>(handler))
|
||||
.Where(p => p is not null)
|
||||
.FirstOrDefault();
|
||||
if (details is not null)
|
||||
{
|
||||
context.Model.ReceivedConfirmations = details.ConfirmationCount;
|
||||
context.Model.RequiredConfirmations = (int)ZanoListener.ConfirmationsRequired(details, context.InvoiceEntity.SpeedPolicy);
|
||||
context.Model.RequiredConfirmations = (int)LetheanListener.ConfirmationsRequired(details, context.InvoiceEntity.SpeedPolicy);
|
||||
}
|
||||
|
||||
context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BTCPayServer.Plugins.Zano.Payments
|
||||
namespace BTCPayServer.Plugins.Lethean.Payments
|
||||
{
|
||||
public class ZanoOnChainPaymentMethodDetails
|
||||
public class LetheanOnChainPaymentMethodDetails
|
||||
{
|
||||
public string PaymentId { get; set; }
|
||||
public long? InvoiceSettledConfirmationThreshold { get; set; }
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BTCPayServer.Plugins.Zano.Payments
|
||||
namespace BTCPayServer.Plugins.Lethean.Payments
|
||||
{
|
||||
public class ZanoPaymentData
|
||||
public class LetheanPaymentData
|
||||
{
|
||||
public string PaymentId { get; set; }
|
||||
public long BlockHeight { get; set; }
|
||||
|
|
@ -6,13 +6,13 @@ using BTCPayServer.Services.Invoices;
|
|||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Payments
|
||||
namespace BTCPayServer.Plugins.Lethean.Payments
|
||||
{
|
||||
public class ZanoPaymentLinkExtension : IPaymentLinkExtension
|
||||
public class LetheanPaymentLinkExtension : IPaymentLinkExtension
|
||||
{
|
||||
private readonly ZanoSpecificBtcPayNetwork _network;
|
||||
private readonly LetheanSpecificBtcPayNetwork _network;
|
||||
|
||||
public ZanoPaymentLinkExtension(PaymentMethodId paymentMethodId, ZanoSpecificBtcPayNetwork network)
|
||||
public LetheanPaymentLinkExtension(PaymentMethodId paymentMethodId, LetheanSpecificBtcPayNetwork network)
|
||||
{
|
||||
PaymentMethodId = paymentMethodId;
|
||||
_network = network;
|
||||
|
|
@ -4,36 +4,36 @@ using System.Threading.Tasks;
|
|||
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Plugins.Zano.RPC.Models;
|
||||
using BTCPayServer.Plugins.Zano.Services;
|
||||
using BTCPayServer.Plugins.Zano.Utils;
|
||||
using BTCPayServer.Plugins.Lethean.RPC.Models;
|
||||
using BTCPayServer.Plugins.Lethean.Services;
|
||||
using BTCPayServer.Plugins.Lethean.Utils;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Payments
|
||||
namespace BTCPayServer.Plugins.Lethean.Payments
|
||||
{
|
||||
public class ZanoPaymentMethodHandler : IPaymentMethodHandler
|
||||
public class LetheanPaymentMethodHandler : IPaymentMethodHandler
|
||||
{
|
||||
private readonly ZanoSpecificBtcPayNetwork _network;
|
||||
public ZanoSpecificBtcPayNetwork Network => _network;
|
||||
private readonly LetheanSpecificBtcPayNetwork _network;
|
||||
public LetheanSpecificBtcPayNetwork Network => _network;
|
||||
public JsonSerializer Serializer { get; }
|
||||
private readonly ZanoRpcProvider _zanoRpcProvider;
|
||||
private readonly LetheanRpcProvider _letheanRpcProvider;
|
||||
|
||||
public PaymentMethodId PaymentMethodId { get; }
|
||||
|
||||
// Fixed fee: 0.01 ZANO in atomic units (12 decimals)
|
||||
// Fixed fee: 0.01 LTHN in atomic units (12 decimals)
|
||||
private const long FixedFeeAtomicUnits = 10_000_000_000;
|
||||
|
||||
public ZanoPaymentMethodHandler(ZanoSpecificBtcPayNetwork network, ZanoRpcProvider zanoRpcProvider)
|
||||
public LetheanPaymentMethodHandler(LetheanSpecificBtcPayNetwork network, LetheanRpcProvider letheanRpcProvider)
|
||||
{
|
||||
PaymentMethodId = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode);
|
||||
_network = network;
|
||||
Serializer = BlobSerializer.CreateSerializer().Serializer;
|
||||
_zanoRpcProvider = zanoRpcProvider;
|
||||
_letheanRpcProvider = letheanRpcProvider;
|
||||
}
|
||||
|
||||
bool IsReady() => _zanoRpcProvider.IsConfigured(_network.CryptoCode) && _zanoRpcProvider.IsAvailable(_network.CryptoCode);
|
||||
bool IsReady() => _letheanRpcProvider.IsConfigured(_network.CryptoCode) && _letheanRpcProvider.IsAvailable(_network.CryptoCode);
|
||||
|
||||
public Task BeforeFetchingRates(PaymentMethodContext context)
|
||||
{
|
||||
|
|
@ -44,7 +44,7 @@ namespace BTCPayServer.Plugins.Zano.Payments
|
|||
try
|
||||
{
|
||||
var paymentId = GeneratePaymentId();
|
||||
var walletClient = _zanoRpcProvider.WalletRpcClients[_network.CryptoCode];
|
||||
var walletClient = _letheanRpcProvider.WalletRpcClients[_network.CryptoCode];
|
||||
context.State = new Prepare()
|
||||
{
|
||||
ReserveAddress = walletClient.SendCommandAsync<MakeIntegratedAddressRequest, MakeIntegratedAddressResponse>(
|
||||
|
|
@ -63,32 +63,32 @@ namespace BTCPayServer.Plugins.Zano.Payments
|
|||
|
||||
public async Task ConfigurePrompt(PaymentMethodContext context)
|
||||
{
|
||||
if (!_zanoRpcProvider.IsConfigured(_network.CryptoCode))
|
||||
if (!_letheanRpcProvider.IsConfigured(_network.CryptoCode))
|
||||
{
|
||||
throw new PaymentMethodUnavailableException("BTCPAY_ZANO_WALLET_DAEMON_URI or BTCPAY_ZANO_DAEMON_URI isn't configured");
|
||||
throw new PaymentMethodUnavailableException("BTCPAY_LTHN_WALLET_DAEMON_URI or BTCPAY_LTHN_DAEMON_URI isn't configured");
|
||||
}
|
||||
|
||||
if (!_zanoRpcProvider.IsAvailable(_network.CryptoCode) || context.State is not Prepare zanoPrepare)
|
||||
if (!_letheanRpcProvider.IsAvailable(_network.CryptoCode) || context.State is not Prepare letheanPrepare)
|
||||
{
|
||||
throw new PaymentMethodUnavailableException("Node or wallet not available");
|
||||
}
|
||||
|
||||
var address = await zanoPrepare.ReserveAddress;
|
||||
var address = await letheanPrepare.ReserveAddress;
|
||||
|
||||
var details = new ZanoOnChainPaymentMethodDetails()
|
||||
var details = new LetheanOnChainPaymentMethodDetails()
|
||||
{
|
||||
PaymentId = zanoPrepare.PaymentId,
|
||||
PaymentId = letheanPrepare.PaymentId,
|
||||
InvoiceSettledConfirmationThreshold = ParsePaymentMethodConfig(context.PaymentMethodConfig).InvoiceSettledConfirmationThreshold
|
||||
};
|
||||
context.Prompt.Destination = address.IntegratedAddress;
|
||||
context.Prompt.PaymentMethodFee = ZanoMoney.Convert(FixedFeeAtomicUnits);
|
||||
context.Prompt.PaymentMethodFee = LetheanMoney.Convert(FixedFeeAtomicUnits);
|
||||
context.Prompt.Details = JObject.FromObject(details, Serializer);
|
||||
context.TrackedDestinations.Add(address.IntegratedAddress);
|
||||
}
|
||||
|
||||
private ZanoPaymentPromptDetails ParsePaymentMethodConfig(JToken config)
|
||||
private LetheanPaymentPromptDetails ParsePaymentMethodConfig(JToken config)
|
||||
{
|
||||
return config.ToObject<ZanoPaymentPromptDetails>(Serializer) ?? throw new FormatException($"Invalid {nameof(ZanoPaymentMethodHandler)}");
|
||||
return config.ToObject<LetheanPaymentPromptDetails>(Serializer) ?? throw new FormatException($"Invalid {nameof(LetheanPaymentMethodHandler)}");
|
||||
}
|
||||
object IPaymentMethodHandler.ParsePaymentMethodConfig(JToken config)
|
||||
{
|
||||
|
|
@ -101,18 +101,18 @@ namespace BTCPayServer.Plugins.Zano.Payments
|
|||
public string PaymentId;
|
||||
}
|
||||
|
||||
public ZanoOnChainPaymentMethodDetails ParsePaymentPromptDetails(JToken details)
|
||||
public LetheanOnChainPaymentMethodDetails ParsePaymentPromptDetails(JToken details)
|
||||
{
|
||||
return details.ToObject<ZanoOnChainPaymentMethodDetails>(Serializer);
|
||||
return details.ToObject<LetheanOnChainPaymentMethodDetails>(Serializer);
|
||||
}
|
||||
object IPaymentMethodHandler.ParsePaymentPromptDetails(JToken details)
|
||||
{
|
||||
return ParsePaymentPromptDetails(details);
|
||||
}
|
||||
|
||||
public ZanoPaymentData ParsePaymentDetails(JToken details)
|
||||
public LetheanPaymentData ParsePaymentDetails(JToken details)
|
||||
{
|
||||
return details.ToObject<ZanoPaymentData>(Serializer) ?? throw new FormatException($"Invalid {nameof(ZanoPaymentMethodHandler)}");
|
||||
return details.ToObject<LetheanPaymentData>(Serializer) ?? throw new FormatException($"Invalid {nameof(LetheanPaymentMethodHandler)}");
|
||||
}
|
||||
object IPaymentMethodHandler.ParsePaymentDetails(JToken details)
|
||||
{
|
||||
7
Plugins/Lethean/Payments/LetheanPaymentPromptDetails.cs
Normal file
7
Plugins/Lethean/Payments/LetheanPaymentPromptDetails.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace BTCPayServer.Plugins.Lethean.Payments
|
||||
{
|
||||
public class LetheanPaymentPromptDetails
|
||||
{
|
||||
public long? InvoiceSettledConfirmationThreshold { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC
|
||||
{
|
||||
public class JsonRpcClient
|
||||
{
|
||||
7
Plugins/Lethean/RPC/LetheanEvent.cs
Normal file
7
Plugins/Lethean/RPC/LetheanEvent.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace BTCPayServer.Plugins.Lethean.RPC
|
||||
{
|
||||
public class LetheanPollEvent
|
||||
{
|
||||
public string CryptoCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class ErrorResponse
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models;
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models;
|
||||
|
||||
public class GetBalanceResponse
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@ using System.Collections.Generic;
|
|||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class GetBulkPaymentsRequest
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@ using System.Collections.Generic;
|
|||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class GetBulkPaymentsResponse
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class GetInfoResponse
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class GetWalletInfoResponse
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class MakeIntegratedAddressRequest
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class MakeIntegratedAddressResponse
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class OpenWalletRequest
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class OpenWalletResponse
|
||||
{
|
||||
|
|
@ -3,7 +3,7 @@ using System.Globalization;
|
|||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.RPC.Models
|
||||
namespace BTCPayServer.Plugins.Lethean.RPC.Models
|
||||
{
|
||||
public class ParseStringConverter : JsonConverter
|
||||
{
|
||||
|
|
@ -9,11 +9,11 @@ using BTCPayServer.Data;
|
|||
using BTCPayServer.Events;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
using BTCPayServer.Plugins.Zano.Payments;
|
||||
using BTCPayServer.Plugins.Zano.RPC;
|
||||
using BTCPayServer.Plugins.Zano.RPC.Models;
|
||||
using BTCPayServer.Plugins.Zano.Utils;
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
using BTCPayServer.Plugins.Lethean.Payments;
|
||||
using BTCPayServer.Plugins.Lethean.RPC;
|
||||
using BTCPayServer.Plugins.Lethean.RPC.Models;
|
||||
using BTCPayServer.Plugins.Lethean.Utils;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
|
||||
|
|
@ -21,34 +21,34 @@ using Microsoft.Extensions.Logging;
|
|||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Services
|
||||
namespace BTCPayServer.Plugins.Lethean.Services
|
||||
{
|
||||
public class ZanoListener : EventHostedServiceBase
|
||||
public class LetheanListener : EventHostedServiceBase
|
||||
{
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly ZanoRpcProvider _zanoRpcProvider;
|
||||
private readonly ZanoConfiguration _zanoConfiguration;
|
||||
private readonly LetheanRpcProvider _letheanRpcProvider;
|
||||
private readonly LetheanConfiguration _letheanConfiguration;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly ILogger<ZanoListener> _logger;
|
||||
private readonly ILogger<LetheanListener> _logger;
|
||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||
private readonly InvoiceActivator _invoiceActivator;
|
||||
private readonly PaymentService _paymentService;
|
||||
|
||||
public ZanoListener(InvoiceRepository invoiceRepository,
|
||||
public LetheanListener(InvoiceRepository invoiceRepository,
|
||||
EventAggregator eventAggregator,
|
||||
ZanoRpcProvider zanoRpcProvider,
|
||||
ZanoConfiguration zanoConfiguration,
|
||||
LetheanRpcProvider letheanRpcProvider,
|
||||
LetheanConfiguration letheanConfiguration,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
ILogger<ZanoListener> logger,
|
||||
ILogger<LetheanListener> logger,
|
||||
PaymentMethodHandlerDictionary handlers,
|
||||
InvoiceActivator invoiceActivator,
|
||||
PaymentService paymentService) : base(eventAggregator, logger)
|
||||
{
|
||||
_invoiceRepository = invoiceRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_zanoRpcProvider = zanoRpcProvider;
|
||||
_zanoConfiguration = zanoConfiguration;
|
||||
_letheanRpcProvider = letheanRpcProvider;
|
||||
_letheanConfiguration = letheanConfiguration;
|
||||
_networkProvider = networkProvider;
|
||||
_logger = logger;
|
||||
_handlers = handlers;
|
||||
|
|
@ -59,29 +59,29 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
protected override void SubscribeToEvents()
|
||||
{
|
||||
base.SubscribeToEvents();
|
||||
Subscribe<ZanoPollEvent>();
|
||||
Subscribe<ZanoRpcProvider.ZanoDaemonStateChange>();
|
||||
Subscribe<LetheanPollEvent>();
|
||||
Subscribe<LetheanRpcProvider.LetheanDaemonStateChange>();
|
||||
}
|
||||
|
||||
protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
|
||||
{
|
||||
if (evt is ZanoRpcProvider.ZanoDaemonStateChange stateChange)
|
||||
if (evt is LetheanRpcProvider.LetheanDaemonStateChange stateChange)
|
||||
{
|
||||
if (_zanoRpcProvider.IsAvailable(stateChange.CryptoCode))
|
||||
if (_letheanRpcProvider.IsAvailable(stateChange.CryptoCode))
|
||||
{
|
||||
_logger.LogInformation("{CryptoCode} just became available", stateChange.CryptoCode);
|
||||
_ = UpdateAnyPendingZanoPayment(stateChange.CryptoCode);
|
||||
_ = UpdateAnyPendingLetheanPayment(stateChange.CryptoCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("{CryptoCode} just became unavailable", stateChange.CryptoCode);
|
||||
}
|
||||
}
|
||||
else if (evt is ZanoPollEvent pollEvent)
|
||||
else if (evt is LetheanPollEvent pollEvent)
|
||||
{
|
||||
if (_zanoRpcProvider.IsAvailable(pollEvent.CryptoCode))
|
||||
if (_letheanRpcProvider.IsAvailable(pollEvent.CryptoCode))
|
||||
{
|
||||
await UpdateAnyPendingZanoPayment(pollEvent.CryptoCode);
|
||||
await UpdateAnyPendingLetheanPayment(pollEvent.CryptoCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -114,14 +114,14 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
return;
|
||||
}
|
||||
|
||||
var walletRpcClient = _zanoRpcProvider.WalletRpcClients[cryptoCode];
|
||||
var walletRpcClient = _letheanRpcProvider.WalletRpcClients[cryptoCode];
|
||||
var network = _networkProvider.GetNetwork(cryptoCode);
|
||||
var paymentMethodId = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode);
|
||||
var handler = (ZanoPaymentMethodHandler)_handlers[paymentMethodId];
|
||||
var handler = (LetheanPaymentMethodHandler)_handlers[paymentMethodId];
|
||||
|
||||
// Get current daemon height for confirmation calculation
|
||||
long currentHeight = 0;
|
||||
if (_zanoRpcProvider.Summaries.TryGetValue(cryptoCode, out var summary))
|
||||
if (_letheanRpcProvider.Summaries.TryGetValue(cryptoCode, out var summary))
|
||||
{
|
||||
currentHeight = summary.CurrentHeight;
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
// Collect all payment_ids from pending invoices
|
||||
var expandedInvoices = invoices.Select(entity => (
|
||||
Invoice: entity,
|
||||
ExistingPayments: GetAllZanoPayments(entity, cryptoCode),
|
||||
ExistingPayments: GetAllLetheanPayments(entity, cryptoCode),
|
||||
Prompt: entity.GetPaymentPrompt(paymentMethodId),
|
||||
PaymentMethodDetails: handler.ParsePaymentPromptDetails(entity.GetPaymentPrompt(paymentMethodId).Details)))
|
||||
.ToList();
|
||||
|
|
@ -174,7 +174,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
var updatedPaymentEntities = new List<(PaymentEntity Payment, InvoiceEntity invoice)>();
|
||||
var processingTasks = new List<Task>();
|
||||
|
||||
// Deduplicate: Zano returns both confirmed (block_height>0) and mempool (block_height=0)
|
||||
// Deduplicate: Lethean returns both confirmed (block_height>0) and mempool (block_height=0)
|
||||
// entries for the same tx. Keep the confirmed entry when available.
|
||||
var dedupedPayments = result.Payments
|
||||
.GroupBy(p => $"{p.TxHash}#{p.PaymentId}")
|
||||
|
|
@ -222,7 +222,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
}
|
||||
|
||||
private async Task UpdateExistingPaymentConfirmations(string cryptoCode, InvoiceEntity[] invoices,
|
||||
ZanoPaymentMethodHandler handler, long currentHeight)
|
||||
LetheanPaymentMethodHandler handler, long currentHeight)
|
||||
{
|
||||
if (currentHeight <= 0)
|
||||
{
|
||||
|
|
@ -233,7 +233,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
|
||||
foreach (var invoice in invoices)
|
||||
{
|
||||
var existingPayments = GetAllZanoPayments(invoice, cryptoCode);
|
||||
var existingPayments = GetAllLetheanPayments(invoice, cryptoCode);
|
||||
foreach (var payment in existingPayments)
|
||||
{
|
||||
var data = handler.ParsePaymentDetails(payment.Details);
|
||||
|
|
@ -268,9 +268,9 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
{
|
||||
var network = _networkProvider.GetNetwork(cryptoCode);
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode);
|
||||
var handler = (ZanoPaymentMethodHandler)_handlers[pmi];
|
||||
var handler = (LetheanPaymentMethodHandler)_handlers[pmi];
|
||||
var promptDetails = handler.ParsePaymentPromptDetails(invoice.GetPaymentPrompt(pmi).Details);
|
||||
var details = new ZanoPaymentData()
|
||||
var details = new LetheanPaymentData()
|
||||
{
|
||||
PaymentId = paymentId,
|
||||
TransactionId = txId,
|
||||
|
|
@ -283,7 +283,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
var paymentData = new PaymentData()
|
||||
{
|
||||
Status = status,
|
||||
Amount = ZanoMoney.Convert(totalAmount),
|
||||
Amount = LetheanMoney.Convert(totalAmount),
|
||||
Created = DateTimeOffset.UtcNow,
|
||||
Id = $"{txId}#{paymentId}",
|
||||
Currency = network.CryptoCode,
|
||||
|
|
@ -291,7 +291,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
}.Set(invoice, handler, details);
|
||||
|
||||
// Check if this tx exists as a payment to this invoice already
|
||||
var alreadyExistingPayment = GetAllZanoPayments(invoice, cryptoCode)
|
||||
var alreadyExistingPayment = GetAllLetheanPayments(invoice, cryptoCode)
|
||||
.SingleOrDefault(c => c.Id == paymentData.Id && c.PaymentMethodId == pmi);
|
||||
|
||||
if (alreadyExistingPayment == null)
|
||||
|
|
@ -311,10 +311,10 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
}
|
||||
}
|
||||
|
||||
private bool GetStatus(ZanoPaymentData details, SpeedPolicy speedPolicy)
|
||||
private bool GetStatus(LetheanPaymentData details, SpeedPolicy speedPolicy)
|
||||
=> ConfirmationsRequired(details, speedPolicy) <= details.ConfirmationCount;
|
||||
|
||||
public static long ConfirmationsRequired(ZanoPaymentData details, SpeedPolicy speedPolicy)
|
||||
public static long ConfirmationsRequired(LetheanPaymentData details, SpeedPolicy speedPolicy)
|
||||
=> (details, speedPolicy) switch
|
||||
{
|
||||
(_, _) when details.ConfirmationCount < details.LockTime =>
|
||||
|
|
@ -327,7 +327,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
_ => 6,
|
||||
};
|
||||
|
||||
private async Task UpdateAnyPendingZanoPayment(string cryptoCode)
|
||||
private async Task UpdateAnyPendingLetheanPayment(string cryptoCode)
|
||||
{
|
||||
var paymentMethodId = PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode);
|
||||
var invoices = await _invoiceRepository.GetMonitoredInvoices(paymentMethodId);
|
||||
|
|
@ -339,7 +339,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
await UpdatePaymentStates(cryptoCode, invoices);
|
||||
}
|
||||
|
||||
private IEnumerable<PaymentEntity> GetAllZanoPayments(InvoiceEntity invoice, string cryptoCode)
|
||||
private IEnumerable<PaymentEntity> GetAllLetheanPayments(InvoiceEntity invoice, string cryptoCode)
|
||||
{
|
||||
return invoice.GetPayments(false)
|
||||
.Where(p => p.PaymentMethodId == PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode));
|
||||
|
|
@ -3,25 +3,25 @@ using System.IO;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
using BTCPayServer.Plugins.Zano.RPC.Models;
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
using BTCPayServer.Plugins.Lethean.RPC.Models;
|
||||
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Services;
|
||||
namespace BTCPayServer.Plugins.Lethean.Services;
|
||||
|
||||
public class ZanoLoadUpService : IHostedService
|
||||
public class LetheanLoadUpService : IHostedService
|
||||
{
|
||||
private const string CryptoCode = "ZANO";
|
||||
private readonly ILogger<ZanoLoadUpService> _logger;
|
||||
private readonly ZanoRpcProvider _zanoRpcProvider;
|
||||
private readonly ZanoConfiguration _zanoConfiguration;
|
||||
private const string CryptoCode = "LTHN";
|
||||
private readonly ILogger<LetheanLoadUpService> _logger;
|
||||
private readonly LetheanRpcProvider _letheanRpcProvider;
|
||||
private readonly LetheanConfiguration _letheanConfiguration;
|
||||
|
||||
public ZanoLoadUpService(ILogger<ZanoLoadUpService> logger, ZanoRpcProvider zanoRpcProvider, ZanoConfiguration zanoConfiguration)
|
||||
public LetheanLoadUpService(ILogger<LetheanLoadUpService> logger, LetheanRpcProvider letheanRpcProvider, LetheanConfiguration letheanConfiguration)
|
||||
{
|
||||
_zanoRpcProvider = zanoRpcProvider;
|
||||
_zanoConfiguration = zanoConfiguration;
|
||||
_letheanRpcProvider = letheanRpcProvider;
|
||||
_letheanConfiguration = letheanConfiguration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -29,31 +29,31 @@ public class ZanoLoadUpService : IHostedService
|
|||
{
|
||||
try
|
||||
{
|
||||
if (!_zanoConfiguration.ZanoConfigurationItems.TryGetValue(CryptoCode, out var configItem))
|
||||
if (!_letheanConfiguration.LetheanConfigurationItems.TryGetValue(CryptoCode, out var configItem))
|
||||
{
|
||||
_logger.LogInformation("No Zano configuration found, skipping wallet load");
|
||||
_logger.LogInformation("No Lethean configuration found, skipping wallet load");
|
||||
return;
|
||||
}
|
||||
|
||||
var walletDir = configItem.WalletDirectory;
|
||||
if (!string.IsNullOrEmpty(walletDir))
|
||||
{
|
||||
_logger.LogInformation("Attempting to load existing Zano wallet");
|
||||
_logger.LogInformation("Attempting to load existing Lethean wallet");
|
||||
|
||||
string password = await TryToGetPassword(walletDir, cancellationToken);
|
||||
|
||||
await _zanoRpcProvider.WalletRpcClients[CryptoCode]
|
||||
await _letheanRpcProvider.WalletRpcClients[CryptoCode]
|
||||
.SendCommandAsync<OpenWalletRequest, OpenWalletResponse>("open_wallet",
|
||||
new OpenWalletRequest { Filename = "wallet", Password = password }, cancellationToken);
|
||||
|
||||
await _zanoRpcProvider.UpdateSummary(CryptoCode);
|
||||
_logger.LogInformation("Existing Zano wallet successfully loaded");
|
||||
await _letheanRpcProvider.UpdateSummary(CryptoCode);
|
||||
_logger.LogInformation("Existing Lethean wallet successfully loaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("No wallet directory configured. Wallet should be pre-opened in simplewallet RPC mode.");
|
||||
// Still try to update summary — wallet may already be running in RPC mode
|
||||
await _zanoRpcProvider.UpdateSummary(CryptoCode);
|
||||
await _letheanRpcProvider.UpdateSummary(CryptoCode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -4,33 +4,33 @@ using System.Collections.Immutable;
|
|||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
using BTCPayServer.Plugins.Zano.RPC;
|
||||
using BTCPayServer.Plugins.Zano.RPC.Models;
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
using BTCPayServer.Plugins.Lethean.RPC;
|
||||
using BTCPayServer.Plugins.Lethean.RPC.Models;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Services
|
||||
namespace BTCPayServer.Plugins.Lethean.Services
|
||||
{
|
||||
public class ZanoRpcProvider
|
||||
public class LetheanRpcProvider
|
||||
{
|
||||
private readonly ZanoConfiguration _zanoConfiguration;
|
||||
private readonly LetheanConfiguration _letheanConfiguration;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
public ImmutableDictionary<string, JsonRpcClient> DaemonRpcClients;
|
||||
public ImmutableDictionary<string, JsonRpcClient> WalletRpcClients;
|
||||
|
||||
public ConcurrentDictionary<string, ZanoSummary> Summaries { get; } = new();
|
||||
public ConcurrentDictionary<string, LetheanSummary> Summaries { get; } = new();
|
||||
|
||||
public ZanoRpcProvider(ZanoConfiguration zanoConfiguration,
|
||||
public LetheanRpcProvider(LetheanConfiguration letheanConfiguration,
|
||||
EventAggregator eventAggregator,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_zanoConfiguration = zanoConfiguration;
|
||||
_letheanConfiguration = letheanConfiguration;
|
||||
_eventAggregator = eventAggregator;
|
||||
DaemonRpcClients =
|
||||
_zanoConfiguration.ZanoConfigurationItems.ToImmutableDictionary(pair => pair.Key,
|
||||
_letheanConfiguration.LetheanConfigurationItems.ToImmutableDictionary(pair => pair.Key,
|
||||
pair => new JsonRpcClient(pair.Value.DaemonRpcUri,
|
||||
httpClientFactory.CreateClient($"{pair.Key}client")));
|
||||
WalletRpcClients =
|
||||
_zanoConfiguration.ZanoConfigurationItems.ToImmutableDictionary(pair => pair.Key,
|
||||
_letheanConfiguration.LetheanConfigurationItems.ToImmutableDictionary(pair => pair.Key,
|
||||
pair => new JsonRpcClient(pair.Value.InternalWalletRpcUri,
|
||||
httpClientFactory.CreateClient($"{pair.Key}client")));
|
||||
}
|
||||
|
|
@ -42,13 +42,13 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
return Summaries.ContainsKey(cryptoCode) && IsAvailable(Summaries[cryptoCode]);
|
||||
}
|
||||
|
||||
private bool IsAvailable(ZanoSummary summary)
|
||||
private bool IsAvailable(LetheanSummary summary)
|
||||
{
|
||||
return summary.Synced &&
|
||||
summary.WalletAvailable;
|
||||
}
|
||||
|
||||
public async Task<ZanoSummary> UpdateSummary(string cryptoCode)
|
||||
public async Task<LetheanSummary> UpdateSummary(string cryptoCode)
|
||||
{
|
||||
if (!DaemonRpcClients.TryGetValue(cryptoCode.ToUpperInvariant(), out var daemonRpcClient) ||
|
||||
!WalletRpcClients.TryGetValue(cryptoCode.ToUpperInvariant(), out var walletRpcClient))
|
||||
|
|
@ -56,7 +56,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
return null;
|
||||
}
|
||||
|
||||
var summary = new ZanoSummary();
|
||||
var summary = new LetheanSummary();
|
||||
try
|
||||
{
|
||||
var daemonResult =
|
||||
|
|
@ -93,19 +93,19 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
Summaries[cryptoCode] = summary;
|
||||
if (changed)
|
||||
{
|
||||
_eventAggregator.Publish(new ZanoDaemonStateChange() { Summary = summary, CryptoCode = cryptoCode });
|
||||
_eventAggregator.Publish(new LetheanDaemonStateChange() { Summary = summary, CryptoCode = cryptoCode });
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
public class ZanoDaemonStateChange
|
||||
public class LetheanDaemonStateChange
|
||||
{
|
||||
public string CryptoCode { get; set; }
|
||||
public ZanoSummary Summary { get; set; }
|
||||
public LetheanSummary Summary { get; set; }
|
||||
}
|
||||
|
||||
public class ZanoSummary
|
||||
public class LetheanSummary
|
||||
{
|
||||
public bool Synced { get; set; }
|
||||
public long CurrentHeight { get; set; }
|
||||
|
|
@ -3,31 +3,31 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Plugins.Zano.Configuration;
|
||||
using BTCPayServer.Plugins.Zano.RPC;
|
||||
using BTCPayServer.Plugins.Lethean.Configuration;
|
||||
using BTCPayServer.Plugins.Lethean.RPC;
|
||||
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Services
|
||||
namespace BTCPayServer.Plugins.Lethean.Services
|
||||
{
|
||||
public class ZanoSummaryUpdaterHostedService : IHostedService
|
||||
public class LetheanSummaryUpdaterHostedService : IHostedService
|
||||
{
|
||||
private readonly ZanoRpcProvider _zanoRpcProvider;
|
||||
private readonly ZanoConfiguration _zanoConfiguration;
|
||||
private readonly LetheanRpcProvider _letheanRpcProvider;
|
||||
private readonly LetheanConfiguration _letheanConfiguration;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
|
||||
public Logs Logs { get; }
|
||||
|
||||
private CancellationTokenSource _cts;
|
||||
|
||||
public ZanoSummaryUpdaterHostedService(ZanoRpcProvider zanoRpcProvider,
|
||||
ZanoConfiguration zanoConfiguration,
|
||||
public LetheanSummaryUpdaterHostedService(LetheanRpcProvider letheanRpcProvider,
|
||||
LetheanConfiguration letheanConfiguration,
|
||||
EventAggregator eventAggregator,
|
||||
Logs logs)
|
||||
{
|
||||
_zanoRpcProvider = zanoRpcProvider;
|
||||
_zanoConfiguration = zanoConfiguration;
|
||||
_letheanRpcProvider = letheanRpcProvider;
|
||||
_letheanConfiguration = letheanConfiguration;
|
||||
_eventAggregator = eventAggregator;
|
||||
Logs = logs;
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
foreach (var configItem in _zanoConfiguration.ZanoConfigurationItems)
|
||||
foreach (var configItem in _letheanConfiguration.LetheanConfigurationItems)
|
||||
{
|
||||
_ = StartSummaryLoop(_cts.Token, configItem.Key);
|
||||
_ = StartPollingLoop(_cts.Token, configItem.Key);
|
||||
|
|
@ -45,15 +45,15 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
|
||||
private async Task StartSummaryLoop(CancellationToken cancellation, string cryptoCode)
|
||||
{
|
||||
Logs.PayServer.LogInformation("Starting Zano daemon summary updater ({CryptoCode})", cryptoCode);
|
||||
Logs.PayServer.LogInformation("Starting Lethean daemon summary updater ({CryptoCode})", cryptoCode);
|
||||
try
|
||||
{
|
||||
while (!cancellation.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _zanoRpcProvider.UpdateSummary(cryptoCode);
|
||||
if (_zanoRpcProvider.IsAvailable(cryptoCode))
|
||||
await _letheanRpcProvider.UpdateSummary(cryptoCode);
|
||||
if (_letheanRpcProvider.IsAvailable(cryptoCode))
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), cancellation);
|
||||
}
|
||||
|
|
@ -77,16 +77,16 @@ namespace BTCPayServer.Plugins.Zano.Services
|
|||
|
||||
private async Task StartPollingLoop(CancellationToken cancellation, string cryptoCode)
|
||||
{
|
||||
Logs.PayServer.LogInformation("Starting Zano payment polling loop ({CryptoCode})", cryptoCode);
|
||||
Logs.PayServer.LogInformation("Starting Lethean payment polling loop ({CryptoCode})", cryptoCode);
|
||||
try
|
||||
{
|
||||
while (!cancellation.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_zanoRpcProvider.IsAvailable(cryptoCode))
|
||||
if (_letheanRpcProvider.IsAvailable(cryptoCode))
|
||||
{
|
||||
_eventAggregator.Publish(new ZanoPollEvent { CryptoCode = cryptoCode });
|
||||
_eventAggregator.Publish(new LetheanPollEvent { CryptoCode = cryptoCode });
|
||||
}
|
||||
await Task.Delay(TimeSpan.FromSeconds(15), cancellation);
|
||||
}
|
||||
47
Plugins/Lethean/Services/LetheanSyncSummaryProvider.cs
Normal file
47
Plugins/Lethean/Services/LetheanSyncSummaryProvider.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Payments;
|
||||
|
||||
namespace BTCPayServer.Plugins.Lethean.Services
|
||||
{
|
||||
public class LetheanSyncSummaryProvider : ISyncSummaryProvider
|
||||
{
|
||||
private readonly LetheanRpcProvider _letheanRpcProvider;
|
||||
|
||||
public LetheanSyncSummaryProvider(LetheanRpcProvider letheanRpcProvider)
|
||||
{
|
||||
_letheanRpcProvider = letheanRpcProvider;
|
||||
}
|
||||
|
||||
public bool AllAvailable()
|
||||
{
|
||||
return _letheanRpcProvider.Summaries.All(pair => pair.Value.DaemonAvailable);
|
||||
}
|
||||
|
||||
public string Partial { get; } = "/Views/Lethean/LetheanSyncSummary.cshtml";
|
||||
public IEnumerable<ISyncStatus> GetStatuses()
|
||||
{
|
||||
return _letheanRpcProvider.Summaries.Select(pair => new LetheanSyncStatus()
|
||||
{
|
||||
Summary = pair.Value,
|
||||
PaymentMethodId = PaymentMethodId.Parse(pair.Key).ToString()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class LetheanSyncStatus : SyncStatus, ISyncStatus
|
||||
{
|
||||
public override bool Available
|
||||
{
|
||||
get
|
||||
{
|
||||
return Summary?.WalletAvailable ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
public LetheanRpcProvider.LetheanSummary Summary { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Globalization;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Utils
|
||||
namespace BTCPayServer.Plugins.Lethean.Utils
|
||||
{
|
||||
public static class ZanoMoney
|
||||
public static class LetheanMoney
|
||||
{
|
||||
public static decimal Convert(long atomicUnits)
|
||||
{
|
||||
|
|
@ -12,9 +12,9 @@ namespace BTCPayServer.Plugins.Zano.Utils
|
|||
return decimal.Parse(amt, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static long Convert(decimal zano)
|
||||
public static long Convert(decimal lethean)
|
||||
{
|
||||
return System.Convert.ToInt64(zano * 1000000000000);
|
||||
return System.Convert.ToInt64(lethean * 1000000000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ using System;
|
|||
|
||||
using BTCPayServer.Payments;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.ViewModels
|
||||
namespace BTCPayServer.Plugins.Lethean.ViewModels
|
||||
{
|
||||
public class ZanoPaymentViewModel
|
||||
public class LetheanPaymentViewModel
|
||||
{
|
||||
public PaymentMethodId PaymentMethodId { get; set; }
|
||||
public string Confirmations { get; set; }
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@using ZanoPaymentMethodViewModel = BTCPayServer.Plugins.Zano.Controllers.UIZanoStoreController.ZanoPaymentMethodViewModel
|
||||
@using ZanoSettlementThresholdChoice = BTCPayServer.Plugins.Zano.Controllers.UIZanoStoreController.ZanoSettlementThresholdChoice;
|
||||
@model ZanoPaymentMethodViewModel
|
||||
@using LetheanPaymentMethodViewModel = BTCPayServer.Plugins.Lethean.Controllers.UILetheanStoreController.LetheanPaymentMethodViewModel
|
||||
@using LetheanSettlementThresholdChoice = BTCPayServer.Plugins.Lethean.Controllers.UILetheanStoreController.LetheanSettlementThresholdChoice;
|
||||
@model LetheanPaymentMethodViewModel
|
||||
|
||||
@{
|
||||
ViewData.SetActivePage(Model.CryptoCode, StringLocalizer["{0} Settings", Model.CryptoCode], Model.CryptoCode);
|
||||
|
|
@ -30,13 +30,13 @@
|
|||
@if (Model.Summary?.WalletAvailable != true)
|
||||
{
|
||||
<div class="alert alert-info mt-4">
|
||||
<p>To accept Zano payments, you need a Zano wallet running in RPC mode.</p>
|
||||
<p>Start <code>simplewallet</code> with <code>--rpc-bind-port</code> and configure <code>BTCPAY_ZANO_WALLET_DAEMON_URI</code> to point to it.</p>
|
||||
<p>To accept Lethean payments, you need a Lethean wallet running in RPC mode.</p>
|
||||
<p>Start <code>simplewallet</code> with <code>--rpc-bind-port</code> and configure <code>BTCPAY_LTHN_WALLET_DAEMON_URI</code> to point to it.</p>
|
||||
<p>For view-only monitoring, create a watch-only wallet using <code>simplewallet --save_watch_only</code> first.</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<form method="post" asp-action="GetStoreZanoPaymentMethod"
|
||||
<form method="post" asp-action="GetStoreLetheanPaymentMethod"
|
||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||
asp-route-cryptoCode="@Context.GetRouteValue("cryptoCode")"
|
||||
class="mt-4">
|
||||
|
|
@ -56,20 +56,20 @@
|
|||
</a>
|
||||
<select
|
||||
asp-for="SettlementConfirmationThresholdChoice"
|
||||
asp-items="Html.GetEnumSelectList<ZanoSettlementThresholdChoice>()"
|
||||
asp-items="Html.GetEnumSelectList<LetheanSettlementThresholdChoice>()"
|
||||
class="form-select w-auto"
|
||||
onchange="
|
||||
document.getElementById('unconfirmed-warning').hidden = this.value !== '@((int)ZanoSettlementThresholdChoice.ZeroConfirmation)';
|
||||
document.getElementById('custom-confirmation-value').hidden = this.value !== '@((int)ZanoSettlementThresholdChoice.Custom)';">
|
||||
document.getElementById('unconfirmed-warning').hidden = this.value !== '@((int)LetheanSettlementThresholdChoice.ZeroConfirmation)';
|
||||
document.getElementById('custom-confirmation-value').hidden = this.value !== '@((int)LetheanSettlementThresholdChoice.Custom)';">
|
||||
</select>
|
||||
<span asp-validation-for="SettlementConfirmationThresholdChoice" class="text-danger"></span>
|
||||
<p class="info-note my-3 text-warning" id="unconfirmed-warning" role="alert" hidden="@(Model.SettlementConfirmationThresholdChoice is not ZanoSettlementThresholdChoice.ZeroConfirmation)">
|
||||
<p class="info-note my-3 text-warning" id="unconfirmed-warning" role="alert" hidden="@(Model.SettlementConfirmationThresholdChoice is not LetheanSettlementThresholdChoice.ZeroConfirmation)">
|
||||
<vc:icon symbol="warning" />
|
||||
<span text-translate="true">Choosing to accept an unconfirmed invoice can lead to double-spending and is strongly discouraged.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="custom-confirmation-value" hidden="@(Model.SettlementConfirmationThresholdChoice is not ZanoSettlementThresholdChoice.Custom)">
|
||||
<div class="form-group" id="custom-confirmation-value" hidden="@(Model.SettlementConfirmationThresholdChoice is not LetheanSettlementThresholdChoice.Custom)">
|
||||
<label asp-for="CustomSettlementConfirmationThreshold" class="form-label"></label>
|
||||
<input
|
||||
asp-for="CustomSettlementConfirmationThreshold"
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
@using BTCPayServer.Plugins.Zano.Services
|
||||
@inject ZanoRpcProvider ZanoRpcProvider
|
||||
@using BTCPayServer.Plugins.Lethean.Services
|
||||
@inject LetheanRpcProvider LetheanRpcProvider
|
||||
@inject SignInManager<ApplicationUser> SignInManager;
|
||||
|
||||
@if (SignInManager.IsSignedIn(User) && User.IsInRole(Roles.ServerAdmin) && ZanoRpcProvider.Summaries.Any())
|
||||
@if (SignInManager.IsSignedIn(User) && User.IsInRole(Roles.ServerAdmin) && LetheanRpcProvider.Summaries.Any())
|
||||
{
|
||||
@foreach (var summary in ZanoRpcProvider.Summaries)
|
||||
@foreach (var summary in LetheanRpcProvider.Summaries)
|
||||
{
|
||||
@if (summary.Value != null)
|
||||
{
|
||||
|
|
@ -1,42 +1,42 @@
|
|||
@using BTCPayServer.Plugins.Zano.Configuration
|
||||
@using BTCPayServer.Plugins.Zano.Controllers
|
||||
@using BTCPayServer.Plugins.Lethean.Configuration
|
||||
@using BTCPayServer.Plugins.Lethean.Controllers
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Payments
|
||||
@using BTCPayServer.Plugins.Zano.Payments
|
||||
@using BTCPayServer.Plugins.Lethean.Payments
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@inject SignInManager<ApplicationUser> SignInManager;
|
||||
@inject ZanoConfiguration ZanoConfiguration;
|
||||
@inject LetheanConfiguration LetheanConfiguration;
|
||||
@inject IScopeProvider ScopeProvider
|
||||
@inject PaymentMethodHandlerDictionary Handlers
|
||||
@{
|
||||
var storeId = ScopeProvider.GetCurrentStoreId();
|
||||
}
|
||||
@if (SignInManager.IsSignedIn(User) && User.IsInRole(Roles.ServerAdmin) && ZanoConfiguration.ZanoConfigurationItems.Any())
|
||||
@if (SignInManager.IsSignedIn(User) && User.IsInRole(Roles.ServerAdmin) && LetheanConfiguration.LetheanConfigurationItems.Any())
|
||||
{
|
||||
var store = Context.GetStoreData();
|
||||
var excludeFilters = store.GetStoreBlob().GetExcludedPaymentMethods();
|
||||
|
||||
foreach (var configItem in ZanoConfiguration.ZanoConfigurationItems)
|
||||
foreach (var configItem in LetheanConfiguration.LetheanConfigurationItems)
|
||||
{
|
||||
var cryptoCode = configItem.Key;
|
||||
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode);
|
||||
var settings = store.GetPaymentMethodConfigs(Handlers)
|
||||
.Where(s => s.Value is ZanoPaymentPromptDetails && s.Key == pmi)
|
||||
.Where(s => s.Value is LetheanPaymentPromptDetails && s.Key == pmi)
|
||||
.Select(s => s.Value)
|
||||
.SingleOrDefault();
|
||||
var enabled = settings != null && !excludeFilters.Match(pmi);
|
||||
|
||||
var isActive = !string.IsNullOrEmpty(storeId) && ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
||||
nameof(UIZanoStoreController).StartsWith(controller.ToString() ?? string.Empty, StringComparison.InvariantCultureIgnoreCase) &&
|
||||
nameof(UILetheanStoreController).StartsWith(controller.ToString() ?? string.Empty, StringComparison.InvariantCultureIgnoreCase) &&
|
||||
ViewContext.RouteData.Values.TryGetValue("cryptoCode", out var routeCryptoCode) && routeCryptoCode is not null && routeCryptoCode.ToString() == cryptoCode;
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @(isActive ? "active" : "")"
|
||||
asp-route-cryptoCode="@cryptoCode"
|
||||
asp-route-storeId="@storeId"
|
||||
asp-action="GetStoreZanoPaymentMethod"
|
||||
asp-controller="UIZanoStore">
|
||||
asp-action="GetStoreLetheanPaymentMethod"
|
||||
asp-controller="UILetheanStore">
|
||||
<span class="me-2 btcpay-status btcpay-status--@(enabled ? "enabled" : "pending")"></span>
|
||||
<span>@(cryptoCode == "ZANO" ? "Zano" : cryptoCode + " Wallet")</span>
|
||||
<span>@(cryptoCode == "LTHN" ? "Lethean" : cryptoCode + " Wallet")</span>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
@using System.Globalization
|
||||
@using BTCPayServer.Plugins.Zano.Payments
|
||||
@using BTCPayServer.Plugins.Zano.Services
|
||||
@using BTCPayServer.Plugins.Zano.ViewModels
|
||||
@using BTCPayServer.Plugins.Lethean.Payments
|
||||
@using BTCPayServer.Plugins.Lethean.Services
|
||||
@using BTCPayServer.Plugins.Lethean.ViewModels
|
||||
@using BTCPayServer.Services
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
|
|
@ -12,15 +12,15 @@
|
|||
@{
|
||||
var payments = Model.Payments.Select(payment =>
|
||||
{
|
||||
if (!handlers.TryGetValue(payment.PaymentMethodId, out var h) || h is not ZanoPaymentMethodHandler handler)
|
||||
if (!handlers.TryGetValue(payment.PaymentMethodId, out var h) || h is not LetheanPaymentMethodHandler handler)
|
||||
return null;
|
||||
var m = new ZanoPaymentViewModel();
|
||||
var m = new LetheanPaymentViewModel();
|
||||
var onChainPaymentData = handler.ParsePaymentDetails(payment.Details);
|
||||
m.PaymentMethodId = handler.PaymentMethodId;
|
||||
m.DepositAddress = payment.Destination;
|
||||
m.Amount = payment.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
var confReq = ZanoListener.ConfirmationsRequired(onChainPaymentData, payment.InvoiceEntity.SpeedPolicy);
|
||||
var confReq = LetheanListener.ConfirmationsRequired(onChainPaymentData, payment.InvoiceEntity.SpeedPolicy);
|
||||
var confCount = onChainPaymentData.ConfirmationCount;
|
||||
confCount = Math.Min(confReq, confCount);
|
||||
m.Confirmations = $"{confCount} / {confReq}";
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
@if (payments.Any())
|
||||
{
|
||||
<section>
|
||||
<h5>Zano Payments</h5>
|
||||
<h5>Lethean Payments</h5>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -1,42 +1,42 @@
|
|||
# Generate a Zano primary address and obtain its private view key using zano-wallet-cli
|
||||
# Generate a Lethean primary address and obtain its private view key using lethean-wallet-cli
|
||||
|
||||
## Overview
|
||||
|
||||
Note: This tutorial includes instructions for Windows, macOS, and Linux. Skip any steps that do not apply to your operating system.
|
||||
|
||||
In this tutorial, you will generate a Zano primary address and retrieve its associated private view key. These are commonly used when setting up a store or service that needs to receive Zano payments and monitor incoming transactions.
|
||||
In this tutorial, you will generate a Lethean primary address and retrieve its associated private view key. These are commonly used when setting up a store or service that needs to receive Lethean payments and monitor incoming transactions.
|
||||
|
||||
To accomplish this, we will use the Zano command-line wallet `zano-wallet-cli`. This tool is required to create the address and keys, and all wallet creation steps can be completed offline.
|
||||
To accomplish this, we will use the Lethean command-line wallet `lethean-wallet-cli`. This tool is required to create the address and keys, and all wallet creation steps can be completed offline.
|
||||
|
||||
To begin, open a terminal window (Mac/Linux) or command prompt (Windows) and type the following commands:
|
||||
|
||||
```bash
|
||||
# LINUX: Download the Linux 64-bit command line client and extract it
|
||||
wget https://downloads.getzano.org/linux64
|
||||
wget https://downloads.getlethean.org/linux64
|
||||
tar -xvf linux64
|
||||
cd zano-x86_64-linux-gnu-*
|
||||
cd lethean-x86_64-linux-gnu-*
|
||||
|
||||
# MAC: Download the Mac command line client and extract it
|
||||
wget https://downloads.getzano.org/mac64
|
||||
wget https://downloads.getlethean.org/mac64
|
||||
tar -xvf mac64
|
||||
cd zano-x86_64-apple-*
|
||||
cd lethean-x86_64-apple-*
|
||||
|
||||
# WINDOWS: Create a new folder with Windows File Explorer, and use your web browser to download the following file to the new folder
|
||||
https://downloads.getzano.org/win64
|
||||
https://downloads.getlethean.org/win64
|
||||
|
||||
# You are strongly advised to verify the hashes of the archive you downloaded:
|
||||
# https://www.getzano.org/downloads/#cli
|
||||
# https://www.getlethean.org/downloads/#cli
|
||||
|
||||
# WINDOWS: Double click the Zano zip file that has been downloaded to extract it. Then open Command Prompt. Use the 'cd' command to navigate to your new folder
|
||||
cd zano-x86_64-w64-*
|
||||
# WINDOWS: Double click the Lethean zip file that has been downloaded to extract it. Then open Command Prompt. Use the 'cd' command to navigate to your new folder
|
||||
cd lethean-x86_64-w64-*
|
||||
|
||||
# Run the Zano command line wallet.
|
||||
# Run the Lethean command line wallet.
|
||||
# LINUX/MAC:
|
||||
./zano-wallet-cli --offline
|
||||
./lethean-wallet-cli --offline
|
||||
# WINDOWS:
|
||||
zano-wallet-cli.exe --offline
|
||||
lethean-wallet-cli.exe --offline
|
||||
|
||||
# Follow the instructions displayed to create a new wallet. When told the 25 word SEED, write this down on paper and keep it in a very safe place. Even if you forget your passwords, the 25 word SEED can be used to recreate your wallet from any machine and have complete control over your Zano funds. Sample output from the Zano wallet is below:
|
||||
# Follow the instructions displayed to create a new wallet. When told the 25 word SEED, write this down on paper and keep it in a very safe place. Even if you forget your passwords, the 25 word SEED can be used to recreate your wallet from any machine and have complete control over your Lethean funds. Sample output from the Lethean wallet is below:
|
||||
|
||||
# Important: The wallet address, seed phrase, and keys shown below were generated solely for this tutorial and contain no funds. Do not reuse these values.
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ To start synchronizing with the daemon, use the "refresh" command.
|
|||
Use the "help" command to see a simplified list of available commands.
|
||||
Use "help all" command to see the list of all available commands.
|
||||
Use "help <command>" to see a command's documentation.
|
||||
Always use the "exit" command when closing zano-wallet-cli to save
|
||||
Always use the "exit" command when closing lethean-wallet-cli to save
|
||||
your current session's state. Otherwise, you might need to synchronize
|
||||
your wallet again (your wallet keys are NOT at risk in any case).
|
||||
|
||||
|
|
@ -82,14 +82,14 @@ kiwi locker audio react inquest benches oyster present fountain
|
|||
**********************************************************************
|
||||
The daemon is not set up to background mine.
|
||||
With background mining enabled, the daemon will mine when idle and not on battery.
|
||||
Enabling this supports the network you are using, and makes you eligible for receiving new zano
|
||||
Enabling this supports the network you are using, and makes you eligible for receiving new lethean
|
||||
Do you want to do it now? (Y/Yes/N/No): : n
|
||||
Background mining not enabled. Set setup-background-mining to 1 to change.
|
||||
If you are new to Zano, type "welcome" for a brief overview.
|
||||
If you are new to Lethean, type "welcome" for a brief overview.
|
||||
Error: wallet failed to connect to daemon, because it is set to offline mode
|
||||
Background refresh thread started
|
||||
|
||||
# Type "address" to see your public wallet address. You can give this address to anyone, and they will be able to send you Zano. However, NEVER give anyone your 25 word SEED.
|
||||
# Type "address" to see your public wallet address. You can give this address to anyone, and they will be able to send you Lethean. However, NEVER give anyone your 25 word SEED.
|
||||
|
||||
[wallet 45zK2W]: address
|
||||
0 45zK2WxTctfc7h6qFVwoN4eJH1Wcu9spwDk2cCuivssre9sCu7uVEEmCziCkYvGyDwHHM1KNyrbid7zvWZ5XKzmJ5yMPTcE Primary address
|
||||
|
|
@ -102,4 +102,4 @@ secret: 8df34dd4b56bd13a69544d849bd0bce2a675bfc600d9e776ad801a6e9867580d
|
|||
public: 1f562cd2ab81d247b6a5492b619d166157b30ca3d60ffe29d79ffd3fde1bbd2c
|
||||
```
|
||||
|
||||
Congratulations! You have generated a Zano primary address along with its private view key, which can be used to create a view wallet and track incoming payments for your store.
|
||||
Congratulations! You have generated a Lethean primary address along with its private view key, which can be used to create a view wallet and track incoming payments for your store.
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"Identifier": "BTCPayServer.Plugins.Zano",
|
||||
"Name": "Zano",
|
||||
"Version": "1.0.0",
|
||||
"Description": "Accept Zano (ZANO) payments in BTCPay Server. Privacy-focused cryptocurrency with confidential transactions.",
|
||||
"SystemPlugin": false,
|
||||
"Dependencies": [
|
||||
{
|
||||
"Identifier": "BTCPayServer",
|
||||
"Condition": ">=2.1.0"
|
||||
}
|
||||
],
|
||||
"Documentation": "https://github.com/hyle-team/btcpayserver-zano-plugin",
|
||||
"Source": "https://github.com/hyle-team/btcpayserver-zano-plugin",
|
||||
"Author": "Hyle Team",
|
||||
"AuthorLink": "https://github.com/hyle-team"
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Configuration
|
||||
{
|
||||
public class ZanoConfiguration
|
||||
{
|
||||
public Dictionary<string, ZanoConfigurationItem> ZanoConfigurationItems { get; set; } = [];
|
||||
}
|
||||
|
||||
public class ZanoConfigurationItem
|
||||
{
|
||||
public Uri DaemonRpcUri { get; set; }
|
||||
public Uri InternalWalletRpcUri { get; set; }
|
||||
public string WalletDirectory { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
namespace BTCPayServer.Plugins.Zano.Payments
|
||||
{
|
||||
public class ZanoPaymentPromptDetails
|
||||
{
|
||||
public long? InvoiceSettledConfirmationThreshold { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
namespace BTCPayServer.Plugins.Zano.RPC
|
||||
{
|
||||
public class ZanoPollEvent
|
||||
{
|
||||
public string CryptoCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Payments;
|
||||
|
||||
namespace BTCPayServer.Plugins.Zano.Services
|
||||
{
|
||||
public class ZanoSyncSummaryProvider : ISyncSummaryProvider
|
||||
{
|
||||
private readonly ZanoRpcProvider _zanoRpcProvider;
|
||||
|
||||
public ZanoSyncSummaryProvider(ZanoRpcProvider zanoRpcProvider)
|
||||
{
|
||||
_zanoRpcProvider = zanoRpcProvider;
|
||||
}
|
||||
|
||||
public bool AllAvailable()
|
||||
{
|
||||
return _zanoRpcProvider.Summaries.All(pair => pair.Value.DaemonAvailable);
|
||||
}
|
||||
|
||||
public string Partial { get; } = "/Views/Zano/ZanoSyncSummary.cshtml";
|
||||
public IEnumerable<ISyncStatus> GetStatuses()
|
||||
{
|
||||
return _zanoRpcProvider.Summaries.Select(pair => new ZanoSyncStatus()
|
||||
{
|
||||
Summary = pair.Value,
|
||||
PaymentMethodId = PaymentMethodId.Parse(pair.Key).ToString()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class ZanoSyncStatus : SyncStatus, ISyncStatus
|
||||
{
|
||||
public override bool Available
|
||||
{
|
||||
get
|
||||
{
|
||||
return Summary?.WalletAvailable ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
public ZanoRpcProvider.ZanoSummary Summary { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
namespace BTCPayServer.Plugins.Zano;
|
||||
|
||||
public class ZanoSpecificBtcPayNetwork : BTCPayNetworkBase
|
||||
{
|
||||
public int MaxTrackedConfirmation = 10;
|
||||
public string UriScheme { get; set; }
|
||||
}
|
||||
68
README.md
68
README.md
|
|
@ -1,9 +1,9 @@
|
|||
# Zano BTCPay Server Plugin
|
||||
# Lethean BTCPay Server Plugin
|
||||
|
||||
Accept [Zano](https://zano.org) payments in BTCPay Server. Privacy-focused cryptocurrency with confidential transactions and integrated addresses.
|
||||
Accept [Lethean](https://lethean.org) payments in BTCPay Server. Privacy-focused cryptocurrency with confidential transactions and integrated addresses.
|
||||
|
||||
> [!WARNING]
|
||||
> This plugin shares a single Zano wallet across all stores in the BTCPay Server instance. Use this plugin only if you are not sharing your instance.
|
||||
> This plugin shares a single Lethean wallet across all stores in the BTCPay Server instance. Use this plugin only if you are not sharing your instance.
|
||||
|
||||
## How it works
|
||||
|
||||
|
|
@ -13,27 +13,27 @@ When a customer creates an invoice, the plugin generates a unique **integrated a
|
|||
|
||||
| Environment variable | Required | Description | Example |
|
||||
| --- | --- | --- | --- |
|
||||
| `BTCPAY_ZANO_DAEMON_URI` | Yes | URI of the zanod RPC interface | `http://127.0.0.1:11211` |
|
||||
| `BTCPAY_ZANO_WALLET_DAEMON_URI` | Yes | URI of the simplewallet RPC interface | `http://127.0.0.1:11212` |
|
||||
| `BTCPAY_ZANO_WALLET_DAEMON_WALLETDIR` | No | Directory where wallet files are stored (for auto-loading on startup) | `/wallet` |
|
||||
| `BTCPAY_LTHN_DAEMON_URI` | Yes | URI of the letheand RPC interface | `http://127.0.0.1:36941` |
|
||||
| `BTCPAY_LTHN_WALLET_DAEMON_URI` | Yes | URI of the simplewallet RPC interface | `http://127.0.0.1:36944` |
|
||||
| `BTCPAY_LTHN_WALLET_DAEMON_WALLETDIR` | No | Directory where wallet files are stored (for auto-loading on startup) | `/wallet` |
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Run Zano daemon
|
||||
### 1. Run Lethean daemon
|
||||
|
||||
```bash
|
||||
zanod --rpc-bind-ip=0.0.0.0 --rpc-bind-port=11211
|
||||
letheand --rpc-bind-ip=0.0.0.0 --rpc-bind-port=36941
|
||||
```
|
||||
|
||||
### 2. Run Zano wallet in RPC mode
|
||||
### 2. Run Lethean wallet in RPC mode
|
||||
|
||||
Create or open a wallet, then start simplewallet with RPC enabled:
|
||||
|
||||
```bash
|
||||
simplewallet --wallet-file /path/to/wallet \
|
||||
--password "your-password" \
|
||||
--daemon-address 127.0.0.1:11211 \
|
||||
--rpc-bind-port 11212
|
||||
--daemon-address 127.0.0.1:36941 \
|
||||
--rpc-bind-port 36944
|
||||
```
|
||||
|
||||
For receive-only setups, create a watch-only wallet first:
|
||||
|
|
@ -46,37 +46,37 @@ save_watch_only /path/to/watch-only-wallet password
|
|||
|
||||
### 3. Install the plugin
|
||||
|
||||
In BTCPay Server, go to **Server Settings > Plugins** and install the Zano plugin. Then configure the environment variables above and restart.
|
||||
In BTCPay Server, go to **Server Settings > Plugins** and install the Lethean plugin. Then configure the environment variables above and restart.
|
||||
|
||||
### 4. Enable Zano for your store
|
||||
### 4. Enable Lethean for your store
|
||||
|
||||
Go to **Store Settings > Zano** to enable it and set your preferred confirmation threshold.
|
||||
Go to **Store Settings > Lethean** to enable it and set your preferred confirmation threshold.
|
||||
|
||||
## Docker
|
||||
|
||||
A Docker image with zanod and simplewallet is available:
|
||||
A Docker image with letheand and simplewallet is available:
|
||||
|
||||
```bash
|
||||
docker pull pavelravaga/zano:2.2.0.455
|
||||
docker pull letheanio/letheand:latest
|
||||
```
|
||||
|
||||
Run the daemon:
|
||||
```bash
|
||||
docker run -d --name zanod \
|
||||
-p 11211:11211 \
|
||||
-v zano_data:/data \
|
||||
pavelravaga/zano:2.2.0.455
|
||||
docker run -d --name letheand \
|
||||
-p 36941:36941 \
|
||||
-v lethean_data:/data \
|
||||
letheanio/letheand:latest
|
||||
```
|
||||
|
||||
Run the wallet:
|
||||
```bash
|
||||
docker run -d --name zano_wallet \
|
||||
-p 11212:11212 \
|
||||
-v zano_wallet:/wallet \
|
||||
docker run -d --name lethean_wallet \
|
||||
-p 36944:36944 \
|
||||
-v lethean_wallet:/wallet \
|
||||
--entrypoint simplewallet \
|
||||
pavelravaga/zano:2.2.0.455 \
|
||||
--rpc-bind-ip=0.0.0.0 --rpc-bind-port=11212 \
|
||||
--daemon-address=zanod:11211 \
|
||||
letheanio/letheand:latest \
|
||||
--rpc-bind-ip=0.0.0.0 --rpc-bind-port=36944 \
|
||||
--daemon-address=letheand:36941 \
|
||||
--wallet-file=/wallet/wallet --password=""
|
||||
```
|
||||
|
||||
|
|
@ -91,9 +91,9 @@ docker run -d --name zano_wallet \
|
|||
### Clone and build
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/hyle-team/btcpayserver-zano-plugin
|
||||
cd btcpayserver-zano-plugin
|
||||
dotnet build btcpay-zano-plugin.sln
|
||||
git clone --recurse-submodules https://github.com/lethean-io/btcpayserver-lethean-plugin
|
||||
cd btcpayserver-lethean-plugin
|
||||
dotnet build btcpay-lethean-plugin.sln
|
||||
```
|
||||
|
||||
### Run unit tests
|
||||
|
|
@ -121,9 +121,9 @@ Create `appsettings.dev.json` in `btcpayserver/BTCPayServer`:
|
|||
|
||||
```json
|
||||
{
|
||||
"DEBUG_PLUGINS": "../../Plugins/Zano/bin/Debug/net8.0/BTCPayServer.Plugins.Zano.dll",
|
||||
"ZANO_DAEMON_URI": "http://127.0.0.1:11211",
|
||||
"ZANO_WALLET_DAEMON_URI": "http://127.0.0.1:11212"
|
||||
"DEBUG_PLUGINS": "../../Plugins/Lethean/bin/Debug/net8.0/BTCPayServer.Plugins.Lethean.dll",
|
||||
"LTHN_DAEMON_URI": "http://127.0.0.1:36941",
|
||||
"LTHN_WALLET_DAEMON_URI": "http://127.0.0.1:36944"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -133,9 +133,9 @@ Then run BTCPay Server with the plugin loaded.
|
|||
|
||||
- **Address generation**: Integrated addresses with random 8-byte payment IDs (unique per invoice)
|
||||
- **Payment detection**: Polls `get_bulk_payments` every 15 seconds
|
||||
- **Fee**: Fixed 0.01 ZANO per transaction
|
||||
- **Fee**: Fixed 0.01 LTHN per transaction
|
||||
- **Divisibility**: 12 decimal places
|
||||
- **Rate source**: CoinGecko (`ZANO_BTC`)
|
||||
- **Rate source**: CoinGecko (`LTHN_BTC`)
|
||||
- **Confirmations**: Configurable (0, 1, 10, or custom)
|
||||
|
||||
## License
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Supported Versions
|
||||
|
||||
We currently support the following versions of the Zano plugin for BTCPayServer:
|
||||
We currently support the following versions of the Lethean plugin for BTCPayServer:
|
||||
|
||||
| Version | Supported |
|
||||
|---------|-------------|
|
||||
|
|
@ -17,7 +17,7 @@ Please **do not** create public GitHub issues or pull requests for security-rela
|
|||
|
||||
Instead, report it privately by contacting repository admins:
|
||||
|
||||
- Matrix: [#btcpay-zano:matrix.org](https://matrix.to/#/#btcpay-zano:matrix.org)
|
||||
- Matrix: [#btcpay-lethean:matrix.org](https://matrix.to/#/#btcpay-lethean:matrix.org)
|
||||
|
||||
Include as much information as possible:
|
||||
- Vulnerability description
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Tests", "submo
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{C9628212-0A00-4BF2-AF84-21797124579F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.Zano", "Plugins\Zano\BTCPayServer.Plugins.Zano.csproj", "{319C8C91-952F-4CF6-A251-058DFC66D70F}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.Lethean", "Plugins\Lethean\BTCPayServer.Plugins.Lethean.csproj", "{319C8C91-952F-4CF6-A251-058DFC66D70F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.IntegrationTests", "BTCPayServer.Plugins.IntegrationTests\BTCPayServer.Plugins.IntegrationTests.csproj", "{DA3599F0-C2DD-4323-A52F-DED5F86722ED}"
|
||||
EndProject
|
||||
|
|
@ -6,11 +6,11 @@ RUN apt-get update && apt-get install -y \
|
|||
pkg-config && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG ZANO_BRANCH=master
|
||||
RUN git clone --depth 1 --branch ${ZANO_BRANCH} --recursive \
|
||||
https://github.com/hyle-team/zano.git /zano
|
||||
ARG LTHN_BRANCH=master
|
||||
RUN git clone --depth 1 --branch ${LTHN_BRANCH} --recursive \
|
||||
https://github.com/lethean-io/lethean.git /lethean
|
||||
|
||||
WORKDIR /zano/build
|
||||
WORKDIR /lethean/build
|
||||
RUN cmake .. -DCMAKE_BUILD_TYPE=Release && \
|
||||
make -j$(nproc) daemon simplewallet
|
||||
|
||||
|
|
@ -25,14 +25,14 @@ RUN apt-get update && apt-get install -y \
|
|||
libssl3 libunwind8 curl && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /zano/build/src/zanod /usr/local/bin/zanod
|
||||
COPY --from=builder /zano/build/src/simplewallet /usr/local/bin/simplewallet
|
||||
COPY --from=builder /lethean/build/src/letheand /usr/local/bin/letheand
|
||||
COPY --from=builder /lethean/build/src/simplewallet /usr/local/bin/simplewallet
|
||||
|
||||
RUN mkdir -p /data /wallet
|
||||
|
||||
VOLUME ["/data", "/wallet"]
|
||||
|
||||
EXPOSE 11211 11212
|
||||
EXPOSE 36941 36942
|
||||
|
||||
ENTRYPOINT ["zanod"]
|
||||
CMD ["--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=11211", "--data-dir=/data"]
|
||||
ENTRYPOINT ["letheand"]
|
||||
CMD ["--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=36941", "--data-dir=/data"]
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ RUN apt-get update && apt-get install -y \
|
|||
libssl3 libunwind8 curl && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY zanod /usr/local/bin/zanod
|
||||
COPY letheand /usr/local/bin/letheand
|
||||
COPY simplewallet /usr/local/bin/simplewallet
|
||||
|
||||
RUN chmod +x /usr/local/bin/zanod /usr/local/bin/simplewallet && \
|
||||
RUN chmod +x /usr/local/bin/letheand /usr/local/bin/simplewallet && \
|
||||
mkdir -p /data /wallet
|
||||
|
||||
VOLUME ["/data", "/wallet"]
|
||||
|
||||
EXPOSE 11211 11212
|
||||
EXPOSE 36941 36942
|
||||
|
||||
ENTRYPOINT ["zanod"]
|
||||
CMD ["--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=11211", "--data-dir=/data"]
|
||||
ENTRYPOINT ["letheand"]
|
||||
CMD ["--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=36941", "--data-dir=/data"]
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
# BTCPay Server Zano Plugin — Testing Guide
|
||||
# BTCPay Server Lethean Plugin — Testing Guide
|
||||
|
||||
## What is this?
|
||||
|
||||
A BTCPay Server plugin that lets merchants accept Zano (ZANO) payments. When a customer pays an invoice, the plugin:
|
||||
A BTCPay Server plugin that lets merchants accept Lethean (LTHN) payments. When a customer pays an invoice, the plugin:
|
||||
|
||||
1. Generates a unique **integrated address** (embeds a payment ID so each invoice gets its own address)
|
||||
2. Shows a checkout page with QR code, address, and "Pay in wallet" button
|
||||
3. Polls the Zano wallet every 15 seconds via `get_bulk_payments` RPC to detect incoming payments
|
||||
3. Polls the Lethean wallet every 15 seconds via `get_bulk_payments` RPC to detect incoming payments
|
||||
4. Tracks confirmations and settles the invoice based on the merchant's threshold setting
|
||||
|
||||
Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
||||
Built by forking the Monero BTCPay plugin and adapting it for Lethean's RPC API.
|
||||
|
||||
## QA Instance
|
||||
|
||||
- **URL**: https://btcpay.zano.me
|
||||
- **URL**: https://btcpay.lethean.me
|
||||
- **Server**: obscura (157.180.1.140)
|
||||
- **Daemon**: Zano testnet remote node (37.27.100.59:10505)
|
||||
- **Daemon**: Lethean testnet remote node (37.27.100.59:10505)
|
||||
- **Wallet**: freshly generated testnet wallet inside Docker
|
||||
|
||||
---
|
||||
|
|
@ -24,15 +24,15 @@ Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
|||
|
||||
### Prerequisites
|
||||
|
||||
- A Zano testnet wallet with some balance (get testnet ZANO from https://faucet.testnet.zano.org)
|
||||
- A Lethean testnet wallet with some balance (get testnet LTHN from https://faucet.testnet.lethean.org)
|
||||
- A browser
|
||||
|
||||
### Test 1: Setup & Enable Zano
|
||||
### Test 1: Setup & Enable Lethean
|
||||
|
||||
1. Go to https://btcpay.zano.me
|
||||
1. Go to https://btcpay.lethean.me
|
||||
2. Register a new admin account (first user becomes admin)
|
||||
3. Create a store (any name)
|
||||
4. In the left sidebar under **Wallets**, click **Zano**
|
||||
4. In the left sidebar under **Wallets**, click **Lethean**
|
||||
5. **Verify**: The settings page shows:
|
||||
- Node available: True
|
||||
- Wallet RPC available: True
|
||||
|
|
@ -41,21 +41,21 @@ Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
|||
7. Set "Consider the invoice settled when the payment transaction..." to **Zero Confirmation**
|
||||
8. Click **Save**
|
||||
|
||||
**Expected**: Green success message, Zano stays enabled on page reload.
|
||||
**Expected**: Green success message, Lethean stays enabled on page reload.
|
||||
|
||||
### Test 2: Create Invoice with Zano
|
||||
### Test 2: Create Invoice with Lethean
|
||||
|
||||
1. Go to **Invoices** in the sidebar
|
||||
2. Click **Create Invoice**
|
||||
3. Set Amount: `1`, Currency: `ZANO` (USD won't work without a rate source configured)
|
||||
3. Set Amount: `1`, Currency: `LTHN` (USD won't work without a rate source configured)
|
||||
4. Click **Create**
|
||||
5. Click the invoice link to open the checkout page
|
||||
|
||||
**Expected**:
|
||||
- Shows amount: `1.010000000000 ZANO` (1 ZANO + 0.01 network fee)
|
||||
- Shows an integrated address starting with `iZ`
|
||||
- Shows amount: `1.010000000000 LTHN` (1 LTHN + 0.01 network fee)
|
||||
- Shows an integrated address starting with `iTHN`
|
||||
- QR code is displayed
|
||||
- "Pay in wallet" button is present (opens `zano:` URI)
|
||||
- "Pay in wallet" button is present (opens `lethean:` URI)
|
||||
- "View Details" shows the full address and amount breakdown
|
||||
|
||||
### Test 3: Pay an Invoice
|
||||
|
|
@ -66,7 +66,7 @@ Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
|||
```
|
||||
transfer <integrated_address> <amount_in_atomic_units> 10
|
||||
```
|
||||
For 1.01 ZANO: amount = 1010000000000 atomic units
|
||||
For 1.01 LTHN: amount = 1010000000000 atomic units
|
||||
4. Wait up to 30 seconds on the checkout page
|
||||
|
||||
**Expected**:
|
||||
|
|
@ -76,7 +76,7 @@ Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
|||
|
||||
### Test 4: Confirmation Tracking
|
||||
|
||||
1. Set confirmation threshold to **At Least One** in Zano settings
|
||||
1. Set confirmation threshold to **At Least One** in Lethean settings
|
||||
2. Create and pay a new invoice
|
||||
3. Watch the invoice status
|
||||
|
||||
|
|
@ -95,15 +95,15 @@ Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
|||
|
||||
### Test 6: Underpayment
|
||||
|
||||
1. Create an invoice for 2 ZANO
|
||||
2. Send only 1 ZANO to the integrated address
|
||||
1. Create an invoice for 2 LTHN
|
||||
2. Send only 1 LTHN to the integrated address
|
||||
|
||||
**Expected**: Invoice remains in "New" or shows partial payment, doesn't settle.
|
||||
|
||||
### Test 7: Settings Persistence
|
||||
|
||||
1. Enable Zano, set Custom confirmation threshold to 5
|
||||
2. Save, navigate away, come back to Zano settings
|
||||
1. Enable Lethean, set Custom confirmation threshold to 5
|
||||
2. Save, navigate away, come back to Lethean settings
|
||||
|
||||
**Expected**: Settings are preserved (Enabled, Custom, value 5).
|
||||
|
||||
|
|
@ -116,16 +116,16 @@ Built by forking the Monero BTCPay plugin and adapting it for Zano's RPC API.
|
|||
- Node.js with `npx tsx` available
|
||||
- Playwright installed (`npm install playwright` in `~/.claude/scripts/`)
|
||||
- BTCPay Server running locally or accessible URL
|
||||
- Zano wallet RPC accessible
|
||||
- Lethean wallet RPC accessible
|
||||
|
||||
### Running the test
|
||||
|
||||
```bash
|
||||
# Against local instance
|
||||
npx tsx ~/.claude/scripts/btcpay-zano-e2e.ts
|
||||
npx tsx ~/.claude/scripts/btcpay-lethean-e2e.ts
|
||||
|
||||
# Against QA instance (edit BASE_URL in the script first)
|
||||
BASE_URL=https://btcpay.zano.me npx tsx ~/.claude/scripts/btcpay-zano-e2e.ts
|
||||
BASE_URL=https://btcpay.lethean.me npx tsx ~/.claude/scripts/btcpay-lethean-e2e.ts
|
||||
```
|
||||
|
||||
### What the script tests
|
||||
|
|
@ -134,29 +134,29 @@ BASE_URL=https://btcpay.zano.me npx tsx ~/.claude/scripts/btcpay-zano-e2e.ts
|
|||
|------|--------|-------------|
|
||||
| 1 | Register admin account | Redirects to dashboard |
|
||||
| 2 | Create store "Test Store" | Store appears in nav |
|
||||
| 3 | Navigate to Zano settings | Shows Node/Wallet status |
|
||||
| 4 | Enable Zano + Zero Confirmation | Settings saved successfully |
|
||||
| 5 | Create 1 ZANO invoice | Invoice created, ID assigned |
|
||||
| 6 | Open checkout page | Integrated address (iZ...) displayed, QR code rendered |
|
||||
| 3 | Navigate to Lethean settings | Shows Node/Wallet status |
|
||||
| 4 | Enable Lethean + Zero Confirmation | Settings saved successfully |
|
||||
| 5 | Create 1 LTHN invoice | Invoice created, ID assigned |
|
||||
| 6 | Open checkout page | Integrated address (iTHN...) displayed, QR code rendered |
|
||||
| 7 | Attempt payment via wallet RPC | Transfer call made (may fail if wallet has no funds) |
|
||||
| 8 | Check invoice status | Status page accessible |
|
||||
|
||||
### Screenshots
|
||||
|
||||
Saved to `/tmp/btcpay-zano-e2e/`:
|
||||
Saved to `/tmp/btcpay-lethean-e2e/`:
|
||||
- `01-landing.png` — Initial page
|
||||
- `06-zano-settings.png` — Zano settings with node status
|
||||
- `07-zano-settings-configured.png` — Enabled + threshold set
|
||||
- `06-lethean-settings.png` — Lethean settings with node status
|
||||
- `07-lethean-settings-configured.png` — Enabled + threshold set
|
||||
- `12-checkout-page.png` — Checkout with QR code and address
|
||||
- `14-invoice-details.png` — Invoice admin view
|
||||
|
||||
### Adapting the script
|
||||
|
||||
Key variables at the top of `btcpay-zano-e2e.ts`:
|
||||
Key variables at the top of `btcpay-lethean-e2e.ts`:
|
||||
|
||||
```typescript
|
||||
const BASE_URL = 'http://127.0.0.1:23002'; // BTCPay Server URL
|
||||
const WALLET_RPC = 'http://127.0.0.1:11212/json_rpc'; // Zano wallet RPC
|
||||
const WALLET_RPC = 'http://127.0.0.1:36944/json_rpc'; // Lethean wallet RPC
|
||||
const EMAIL = 'admin@test.com';
|
||||
const PASSWORD = 'Test1234!Test1234!';
|
||||
```
|
||||
|
|
@ -167,14 +167,14 @@ const PASSWORD = 'Test1234!Test1234!';
|
|||
|
||||
| Symptom | Likely cause |
|
||||
|---------|-------------|
|
||||
| Zano not in sidebar | Plugin not loaded — check BTCPay logs for "Plugins.Zano" |
|
||||
| "Node available: False" | Daemon RPC unreachable — check BTCPAY_ZANO_DAEMON_URI |
|
||||
| Lethean not in sidebar | Plugin not loaded — check BTCPay logs for "Plugins.Lethean" |
|
||||
| "Node available: False" | Daemon RPC unreachable — check BTCPAY_LTHN_DAEMON_URI |
|
||||
| "Wallet RPC available: False" | simplewallet not running or wrong port |
|
||||
| "Synced: False" | Daemon still syncing — wait or use a synced remote node |
|
||||
| Invoice shows no Zano option | Zano not enabled for this store |
|
||||
| Invoice shows no Lethean option | Lethean not enabled for this store |
|
||||
| Payment not detected | Check wallet is connected to same daemon, check get_bulk_payments response |
|
||||
| Wrong amount displayed | Divisibility issue (should be 12 decimal places) |
|
||||
| Address doesn't start with iZ | Integrated address generation failed — check make_integrated_address RPC |
|
||||
| Address doesn't start with iTHN | Integrated address generation failed — check make_integrated_address RPC |
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "8.0.416",
|
||||
"version": "8.0.125",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
<defs
|
||||
id="defs291" />
|
||||
<title
|
||||
id="title282">btcpay-zano</title>
|
||||
id="title282">btcpay-lethean</title>
|
||||
<g
|
||||
id="g1503"
|
||||
transform="matrix(0.3368777,0,0,0.3368777,-0.08027797,0)">
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>btcpay-zano</dc:title>
|
||||
<dc:title>btcpay-lethean</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Loading…
Add table
Reference in a new issue