mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-21 14:04:12 +01:00
Generate a wallet object for all scripts, save source in generatedBy rather than receive label (#4413)
This commit is contained in:
parent
f5c5178f95
commit
9a4dec57d1
13 changed files with 178 additions and 78 deletions
|
@ -2,8 +2,11 @@ using System;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using BTCPayServer.Tests.Logging;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using OpenQA.Selenium;
|
||||
|
@ -15,6 +18,10 @@ namespace BTCPayServer.Tests
|
|||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static Task<KeyPathInformation> ReserveAddressAsync(this BTCPayWallet wallet, DerivationStrategyBase derivationStrategyBase)
|
||||
{
|
||||
return wallet.ReserveAddressAsync(null, derivationStrategyBase, "test");
|
||||
}
|
||||
private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
|
||||
public static string ToJson(this object o) => JsonConvert.SerializeObject(o, Formatting.None, JsonSettings);
|
||||
|
||||
|
|
|
@ -1935,6 +1935,9 @@ namespace BTCPayServer.Tests
|
|||
RedirectURL = "http://toto.com/lol"
|
||||
}
|
||||
});
|
||||
var invoiceObject = await client.GetOnChainWalletObject(user.StoreId, "BTC", new OnChainWalletObjectId("invoice", newInvoice.Id), false);
|
||||
Assert.Contains(invoiceObject.Links.Select(l => l.Type), t => t == "script");
|
||||
|
||||
Assert.EndsWith($"/i/{newInvoice.Id}", newInvoice.CheckoutLink);
|
||||
var controller = tester.PayTester.GetController<UIInvoiceController>(user.UserId, user.StoreId);
|
||||
var model = (PaymentModel)((ViewResult)await controller.Checkout(newInvoice.Id)).Model;
|
||||
|
@ -1968,11 +1971,18 @@ namespace BTCPayServer.Tests
|
|||
Assert.True(store.LazyPaymentMethods);
|
||||
|
||||
invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest() { Amount = 1, Currency = "USD" });
|
||||
invoiceObject = await client.GetOnChainWalletObject(user.StoreId, "BTC", new OnChainWalletObjectId("invoice", invoice.Id), false);
|
||||
Assert.DoesNotContain(invoiceObject.Links.Select(l => l.Type), t => t == "script");
|
||||
|
||||
|
||||
paymentMethods = await client.GetInvoicePaymentMethods(store.Id, invoice.Id);
|
||||
Assert.Single(paymentMethods);
|
||||
Assert.False(paymentMethods.First().Activated);
|
||||
await client.ActivateInvoicePaymentMethod(user.StoreId, invoice.Id,
|
||||
paymentMethods.First().PaymentMethod);
|
||||
invoiceObject = await client.GetOnChainWalletObject(user.StoreId, "BTC", new OnChainWalletObjectId("invoice", invoice.Id), false);
|
||||
Assert.Contains(invoiceObject.Links.Select(l => l.Type), t => t == "script");
|
||||
|
||||
paymentMethods = await client.GetInvoicePaymentMethods(store.Id, invoice.Id);
|
||||
Assert.Single(paymentMethods);
|
||||
Assert.True(paymentMethods.First().Activated);
|
||||
|
@ -2030,12 +2040,16 @@ namespace BTCPayServer.Tests
|
|||
BitcoinAddress.Create(pm.Destination, tester.ExplorerClient.Network.NBitcoinNetwork),
|
||||
new Money(0.0002m, MoneyUnit.BTC));
|
||||
});
|
||||
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
|
||||
Assert.Single(pm.Payments);
|
||||
Assert.Equal(-0.0001m, pm.Due);
|
||||
});
|
||||
|
||||
invoiceObject = await client.GetOnChainWalletObject(user.StoreId, "BTC", new OnChainWalletObjectId("invoice", invoice.Id), false);
|
||||
Assert.Contains(invoiceObject.Links.Select(l => l.Type), t => t == "tx");
|
||||
}
|
||||
|
||||
[Fact(Timeout = 60 * 20 * 1000)]
|
||||
|
|
|
@ -34,32 +34,28 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
private readonly UIInvoiceController _invoiceController;
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly CurrencyNameTable _currencyNameTable;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly PullPaymentHostedService _pullPaymentService;
|
||||
private readonly RateFetcher _rateProvider;
|
||||
private readonly InvoiceActivator _invoiceActivator;
|
||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||
|
||||
public LanguageService LanguageService { get; }
|
||||
|
||||
public GreenfieldInvoiceController(UIInvoiceController invoiceController, InvoiceRepository invoiceRepository,
|
||||
LinkGenerator linkGenerator, LanguageService languageService, BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
EventAggregator eventAggregator, PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
CurrencyNameTable currencyNameTable, BTCPayNetworkProvider networkProvider, RateFetcher rateProvider,
|
||||
CurrencyNameTable currencyNameTable, RateFetcher rateProvider,
|
||||
InvoiceActivator invoiceActivator,
|
||||
PullPaymentHostedService pullPaymentService, ApplicationDbContextFactory dbContextFactory)
|
||||
{
|
||||
_invoiceController = invoiceController;
|
||||
_invoiceRepository = invoiceRepository;
|
||||
_linkGenerator = linkGenerator;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_eventAggregator = eventAggregator;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_currencyNameTable = currencyNameTable;
|
||||
_networkProvider = networkProvider;
|
||||
_networkProvider = btcPayNetworkProvider;
|
||||
_rateProvider = rateProvider;
|
||||
_invoiceActivator = invoiceActivator;
|
||||
_pullPaymentService = pullPaymentService;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
LanguageService = languageService;
|
||||
|
@ -342,8 +338,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
|
||||
if (PaymentMethodId.TryParse(paymentMethod, out var paymentMethodId))
|
||||
{
|
||||
await _invoiceRepository.ActivateInvoicePaymentMethod(_eventAggregator, _btcPayNetworkProvider,
|
||||
_paymentMethodHandlerDictionary, store, invoice, paymentMethodId);
|
||||
await _invoiceActivator.ActivateInvoicePaymentMethod(paymentMethodId, invoice, store);
|
||||
return Ok();
|
||||
}
|
||||
ModelState.AddModelError(nameof(paymentMethod), "Invalid payment method");
|
||||
|
|
|
@ -711,8 +711,7 @@ namespace BTCPayServer.Controllers
|
|||
var paymentMethodDetails = paymentMethod.GetPaymentMethodDetails();
|
||||
if (!paymentMethodDetails.Activated)
|
||||
{
|
||||
if (await _InvoiceRepository.ActivateInvoicePaymentMethod(_EventAggregator, _NetworkProvider,
|
||||
_paymentMethodHandlerDictionary, store, invoice, paymentMethod.GetId()))
|
||||
if (await _invoiceActivator.ActivateInvoicePaymentMethod(paymentMethod.GetId(), invoice, store))
|
||||
{
|
||||
return await GetInvoiceModel(invoiceId, paymentMethodId, lang);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ using BTCPayServer.Logging;
|
|||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Models.PaymentRequestViewModels;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services;
|
||||
|
@ -27,6 +28,7 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using NBitcoin;
|
||||
using NBitpayClient;
|
||||
using BitpayCreateInvoiceRequest = BTCPayServer.Models.BitpayCreateInvoiceRequest;
|
||||
using StoreData = BTCPayServer.Data.StoreData;
|
||||
|
@ -37,6 +39,7 @@ namespace BTCPayServer.Controllers
|
|||
public partial class UIInvoiceController : Controller
|
||||
{
|
||||
readonly InvoiceRepository _InvoiceRepository;
|
||||
private readonly WalletRepository _walletRepository;
|
||||
readonly RateFetcher _RateProvider;
|
||||
readonly StoreRepository _StoreRepository;
|
||||
readonly UserManager<ApplicationUser> _UserManager;
|
||||
|
@ -49,12 +52,14 @@ namespace BTCPayServer.Controllers
|
|||
private readonly LanguageService _languageService;
|
||||
private readonly ExplorerClientProvider _ExplorerClients;
|
||||
private readonly UIWalletsController _walletsController;
|
||||
private readonly InvoiceActivator _invoiceActivator;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
|
||||
public WebhookSender WebhookNotificationManager { get; }
|
||||
|
||||
public UIInvoiceController(
|
||||
InvoiceRepository invoiceRepository,
|
||||
WalletRepository walletRepository,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RateFetcher rateProvider,
|
||||
|
@ -69,11 +74,13 @@ namespace BTCPayServer.Controllers
|
|||
LanguageService languageService,
|
||||
ExplorerClientProvider explorerClients,
|
||||
UIWalletsController walletsController,
|
||||
InvoiceActivator invoiceActivator,
|
||||
LinkGenerator linkGenerator)
|
||||
{
|
||||
_CurrencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable));
|
||||
_StoreRepository = storeRepository ?? throw new ArgumentNullException(nameof(storeRepository));
|
||||
_InvoiceRepository = invoiceRepository ?? throw new ArgumentNullException(nameof(invoiceRepository));
|
||||
_walletRepository = walletRepository;
|
||||
_RateProvider = rateProvider ?? throw new ArgumentNullException(nameof(rateProvider));
|
||||
_UserManager = userManager;
|
||||
_EventAggregator = eventAggregator;
|
||||
|
@ -85,6 +92,7 @@ namespace BTCPayServer.Controllers
|
|||
_languageService = languageService;
|
||||
this._ExplorerClients = explorerClients;
|
||||
_walletsController = walletsController;
|
||||
_invoiceActivator = invoiceActivator;
|
||||
_linkGenerator = linkGenerator;
|
||||
}
|
||||
|
||||
|
@ -368,6 +376,30 @@ namespace BTCPayServer.Controllers
|
|||
using (logs.Measure("Saving invoice"))
|
||||
{
|
||||
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, additionalSearchTerms);
|
||||
foreach (var method in paymentMethods)
|
||||
{
|
||||
if (method.GetPaymentMethodDetails() is BitcoinLikeOnChainPaymentMethod bp)
|
||||
{
|
||||
var walletId = new WalletId(store.Id, method.GetId().CryptoCode);
|
||||
await _walletRepository.EnsureWalletObject(new WalletObjectId(
|
||||
walletId,
|
||||
WalletObjectData.Types.Invoice,
|
||||
entity.Id
|
||||
));
|
||||
if (bp.GetDepositAddress(((BTCPayNetwork)method.Network).NBitcoinNetwork) is BitcoinAddress address)
|
||||
{
|
||||
await _walletRepository.EnsureWalletObjectLink(
|
||||
new WalletObjectId(
|
||||
walletId,
|
||||
WalletObjectData.Types.Script,
|
||||
address.ScriptPubKey.ToHex()),
|
||||
new WalletObjectId(
|
||||
walletId,
|
||||
WalletObjectData.Types.Invoice,
|
||||
entity.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
|
|
|
@ -432,6 +432,7 @@ namespace BTCPayServer.Hosting
|
|||
services.AddTransient<UIPaymentRequestController>();
|
||||
// Add application services.
|
||||
services.AddSingleton<EmailSenderFactory>();
|
||||
services.AddSingleton<InvoiceActivator>();
|
||||
|
||||
//create a simple client which hooks up to the http scope
|
||||
services.AddScoped<BTCPayServerClient, LocalBTCPayServerClient>();
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
? null
|
||||
: _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(),
|
||||
ReserveAddress = _WalletProvider.GetWallet(network)
|
||||
.ReserveAddressAsync(supportedPaymentMethod.AccountDerivation)
|
||||
.ReserveAddressAsync(store.Id, supportedPaymentMethod.AccountDerivation, "invoice")
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
btc.GetDepositAddress(wallet.Network.NBitcoinNetwork).ScriptPubKey == paymentData.ScriptPubKey &&
|
||||
paymentMethod.Calculate().Due > Money.Zero)
|
||||
{
|
||||
var address = await wallet.ReserveAddressAsync(strategy);
|
||||
var address = await wallet.ReserveAddressAsync(invoice.StoreId, strategy, "invoice");
|
||||
btc.DepositAddress = address.Address.ToString();
|
||||
btc.KeyPath = address.KeyPath;
|
||||
await _InvoiceRepository.NewPaymentDetails(invoice.Id, btc, wallet.Network);
|
||||
|
|
96
BTCPayServer/Services/InvoiceActivator.cs
Normal file
96
BTCPayServer/Services/InvoiceActivator.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Dom;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Services
|
||||
{
|
||||
public class InvoiceActivator
|
||||
{
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private readonly WalletRepository _walletRepository;
|
||||
|
||||
public InvoiceActivator(
|
||||
InvoiceRepository invoiceRepository,
|
||||
EventAggregator eventAggregator,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
WalletRepository walletRepository)
|
||||
{
|
||||
_invoiceRepository = invoiceRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_walletRepository = walletRepository;
|
||||
}
|
||||
public async Task<bool> ActivateInvoicePaymentMethod(PaymentMethodId paymentMethodId, InvoiceEntity invoice, StoreData store)
|
||||
{
|
||||
if (invoice.GetInvoiceState().Status != InvoiceStatusLegacy.New)
|
||||
return false;
|
||||
bool success = false;
|
||||
var eligibleMethodToActivate = invoice.GetPaymentMethod(paymentMethodId);
|
||||
if (!eligibleMethodToActivate.GetPaymentMethodDetails().Activated)
|
||||
{
|
||||
var payHandler = _paymentMethodHandlerDictionary[paymentMethodId];
|
||||
var supportPayMethod = invoice.GetSupportedPaymentMethod()
|
||||
.Single(method => method.PaymentId == paymentMethodId);
|
||||
var paymentMethod = invoice.GetPaymentMethod(paymentMethodId);
|
||||
var network = _btcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode);
|
||||
var prepare = payHandler.PreparePayment(supportPayMethod, store, network);
|
||||
InvoiceLogs logs = new InvoiceLogs();
|
||||
try
|
||||
{
|
||||
var pmis = invoice.GetPaymentMethods().Select(method => method.GetId()).ToHashSet();
|
||||
logs.Write($"{paymentMethodId}: Activating", InvoiceEventData.EventSeverity.Info);
|
||||
var newDetails = await
|
||||
payHandler.CreatePaymentMethodDetails(logs, supportPayMethod, paymentMethod, store, network,
|
||||
prepare, pmis);
|
||||
eligibleMethodToActivate.SetPaymentMethodDetails(newDetails);
|
||||
await _invoiceRepository.UpdateInvoicePaymentMethod(invoice.Id, eligibleMethodToActivate);
|
||||
|
||||
if (newDetails is BitcoinLikeOnChainPaymentMethod bp)
|
||||
{
|
||||
var walletId = new WalletId(store.Id, paymentMethodId.CryptoCode);
|
||||
if (bp.GetDepositAddress(((BTCPayNetwork)_btcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode)).NBitcoinNetwork) is BitcoinAddress address)
|
||||
{
|
||||
await _walletRepository.EnsureWalletObjectLink(
|
||||
new WalletObjectId(
|
||||
walletId,
|
||||
WalletObjectData.Types.Script,
|
||||
address.ScriptPubKey.ToHex()),
|
||||
new WalletObjectId(
|
||||
walletId,
|
||||
WalletObjectData.Types.Invoice,
|
||||
invoice.Id));
|
||||
}
|
||||
}
|
||||
|
||||
_eventAggregator.Publish(new InvoicePaymentMethodActivated(paymentMethodId, invoice));
|
||||
_eventAggregator.Publish(new InvoiceNeedUpdateEvent(invoice.Id));
|
||||
success = true;
|
||||
}
|
||||
catch (PaymentMethodUnavailableException ex)
|
||||
{
|
||||
logs.Write($"{paymentMethodId}: Payment method unavailable ({ex.Message})", InvoiceEventData.EventSeverity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logs.Write($"{paymentMethodId}: Unexpected exception ({ex})", InvoiceEventData.EventSeverity.Error);
|
||||
}
|
||||
|
||||
await _invoiceRepository.AddInvoiceLogs(invoice.Id, logs);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Payments;
|
||||
|
||||
namespace BTCPayServer.Services.Invoices
|
||||
{
|
||||
public static class InvoiceExtensions
|
||||
{
|
||||
|
||||
public static async Task<bool> ActivateInvoicePaymentMethod(this InvoiceRepository invoiceRepository,
|
||||
EventAggregator eventAggregator, BTCPayNetworkProvider btcPayNetworkProvider, PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
StoreData store, InvoiceEntity invoice, PaymentMethodId paymentMethodId)
|
||||
{
|
||||
if (invoice.GetInvoiceState().Status != InvoiceStatusLegacy.New)
|
||||
return false;
|
||||
bool success = false;
|
||||
var eligibleMethodToActivate = invoice.GetPaymentMethod(paymentMethodId);
|
||||
if (!eligibleMethodToActivate.GetPaymentMethodDetails().Activated)
|
||||
{
|
||||
var payHandler = paymentMethodHandlerDictionary[paymentMethodId];
|
||||
var supportPayMethod = invoice.GetSupportedPaymentMethod()
|
||||
.Single(method => method.PaymentId == paymentMethodId);
|
||||
var paymentMethod = invoice.GetPaymentMethod(paymentMethodId);
|
||||
var network = btcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode);
|
||||
var prepare = payHandler.PreparePayment(supportPayMethod, store, network);
|
||||
InvoiceLogs logs = new InvoiceLogs();
|
||||
try
|
||||
{
|
||||
var pmis = invoice.GetPaymentMethods().Select(method => method.GetId()).ToHashSet();
|
||||
logs.Write($"{paymentMethodId}: Activating", InvoiceEventData.EventSeverity.Info);
|
||||
var newDetails = await
|
||||
payHandler.CreatePaymentMethodDetails(logs, supportPayMethod, paymentMethod, store, network,
|
||||
prepare, pmis);
|
||||
eligibleMethodToActivate.SetPaymentMethodDetails(newDetails);
|
||||
await invoiceRepository.UpdateInvoicePaymentMethod(invoice.Id, eligibleMethodToActivate);
|
||||
eventAggregator.Publish(new InvoicePaymentMethodActivated(paymentMethodId, invoice));
|
||||
eventAggregator.Publish(new InvoiceNeedUpdateEvent(invoice.Id));
|
||||
success = true;
|
||||
}
|
||||
catch (PaymentMethodUnavailableException ex)
|
||||
{
|
||||
logs.Write($"{paymentMethodId}: Payment method unavailable ({ex.Message})", InvoiceEventData.EventSeverity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logs.Write($"{paymentMethodId}: Unexpected exception ({ex})", InvoiceEventData.EventSeverity.Error);
|
||||
}
|
||||
|
||||
await invoiceRepository.AddInvoiceLogs(invoice.Id, logs);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ using NBitcoin;
|
|||
using NBXplorer;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Wallets
|
||||
{
|
||||
|
@ -40,12 +41,14 @@ namespace BTCPayServer.Services.Wallets
|
|||
}
|
||||
public class BTCPayWallet
|
||||
{
|
||||
public WalletRepository WalletRepository { get; }
|
||||
public NBXplorerConnectionFactory NbxplorerConnectionFactory { get; }
|
||||
public Logs Logs { get; }
|
||||
|
||||
private readonly ExplorerClient _Client;
|
||||
private readonly IMemoryCache _MemoryCache;
|
||||
public BTCPayWallet(ExplorerClient client, IMemoryCache memoryCache, BTCPayNetwork network,
|
||||
WalletRepository walletRepository,
|
||||
ApplicationDbContextFactory dbContextFactory, NBXplorerConnectionFactory nbxplorerConnectionFactory, Logs logs)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(client);
|
||||
|
@ -53,6 +56,7 @@ namespace BTCPayServer.Services.Wallets
|
|||
Logs = logs;
|
||||
_Client = client;
|
||||
_Network = network;
|
||||
WalletRepository = walletRepository;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
NbxplorerConnectionFactory = nbxplorerConnectionFactory;
|
||||
_MemoryCache = memoryCache;
|
||||
|
@ -72,8 +76,10 @@ namespace BTCPayServer.Services.Wallets
|
|||
|
||||
public TimeSpan CacheSpan { get; private set; } = TimeSpan.FromMinutes(5);
|
||||
|
||||
public async Task<KeyPathInformation> ReserveAddressAsync(DerivationStrategyBase derivationStrategy)
|
||||
public async Task<KeyPathInformation> ReserveAddressAsync(string storeId, DerivationStrategyBase derivationStrategy, string generatedBy)
|
||||
{
|
||||
if (storeId != null)
|
||||
ArgumentNullException.ThrowIfNull(generatedBy);
|
||||
ArgumentNullException.ThrowIfNull(derivationStrategy);
|
||||
var pathInfo = await _Client.GetUnusedAsync(derivationStrategy, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);
|
||||
// Might happen on some broken install
|
||||
|
@ -82,6 +88,12 @@ namespace BTCPayServer.Services.Wallets
|
|||
await _Client.TrackAsync(derivationStrategy).ConfigureAwait(false);
|
||||
pathInfo = await _Client.GetUnusedAsync(derivationStrategy, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);
|
||||
}
|
||||
if (storeId != null)
|
||||
{
|
||||
await WalletRepository.EnsureWalletObject(
|
||||
new WalletObjectId(new WalletId(storeId, Network.CryptoCode), WalletObjectData.Types.Script, pathInfo.ScriptPubKey.ToHex()),
|
||||
new JObject() { ["generatedBy"] = generatedBy });
|
||||
}
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace BTCPayServer.Services.Wallets
|
|||
{
|
||||
public class BTCPayWalletProvider
|
||||
{
|
||||
public WalletRepository WalletRepository { get; }
|
||||
public Logs Logs { get; }
|
||||
|
||||
private readonly ExplorerClientProvider _Client;
|
||||
|
@ -19,12 +20,14 @@ namespace BTCPayServer.Services.Wallets
|
|||
Data.ApplicationDbContextFactory dbContextFactory,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
NBXplorerConnectionFactory nbxplorerConnectionFactory,
|
||||
WalletRepository walletRepository,
|
||||
Logs logs)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(client);
|
||||
this.Logs = logs;
|
||||
_Client = client;
|
||||
_NetworkProvider = networkProvider;
|
||||
WalletRepository = walletRepository;
|
||||
_Options = memoryCacheOption;
|
||||
|
||||
foreach (var network in networkProvider.GetAll().OfType<BTCPayNetwork>())
|
||||
|
@ -32,7 +35,7 @@ namespace BTCPayServer.Services.Wallets
|
|||
var explorerClient = _Client.GetExplorerClient(network.CryptoCode);
|
||||
if (explorerClient == null)
|
||||
continue;
|
||||
_Wallets.Add(network.CryptoCode.ToUpperInvariant(), new BTCPayWallet(explorerClient, new MemoryCache(_Options), network, dbContextFactory, nbxplorerConnectionFactory, Logs));
|
||||
_Wallets.Add(network.CryptoCode.ToUpperInvariant(), new BTCPayWallet(explorerClient, new MemoryCache(_Options), network, WalletRepository, dbContextFactory, nbxplorerConnectionFactory, Logs));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ using NBitcoin;
|
|||
using NBXplorer;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Wallets
|
||||
{
|
||||
|
@ -75,9 +76,7 @@ namespace BTCPayServer.Services.Wallets
|
|||
return null;
|
||||
}
|
||||
|
||||
var reserve = (await wallet.ReserveAddressAsync(derivationScheme.AccountDerivation));
|
||||
await _walletRepository.AddWalletTransactionAttachment(walletId, reserve.ScriptPubKey.ToHex(), new []{new Attachment("receive")},
|
||||
WalletObjectData.Types.Script);
|
||||
var reserve = (await wallet.ReserveAddressAsync(walletId.StoreId, derivationScheme.AccountDerivation, "receive"));
|
||||
Set(walletId, reserve);
|
||||
return reserve;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue