Files
btcpayserver/BTCPayServer/Components/WalletNav/WalletNav.cs
Andrew Camilleri 6049fa23a7 Support pluginable rate providers (#5777)
* Support pluginable rate providers

This PR allows plugins to provide custom rate providers, that can be contextual to a store. For example, if you use the upcoming fiat offramp plugin, or the Blink plugin, you'll probably want to configure the fetch the rates from them since they are determining the actual fiat rrate to you. However, they require API keys. This PR enables these scenarios, even much more advanced ones, but for example:
* Install fiat offramp plugin
* Configure it
* You can now use the fiat offramp rate provider (no additional config steps beyond selecting the rate source from the select, or maybe the plugin would automatically set it for you once configured)

* Apply suggestions from code review

* Simplify

* Do not use BackgroundFetcherRateProvider for contextual rate prov

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2024-04-30 18:31:15 +09:00

88 lines
3.4 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Controllers;
using BTCPayServer.Data;
using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Services;
using BTCPayServer.Services.Apps;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Wallets;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using NBitcoin;
using NBitcoin.Secp256k1;
namespace BTCPayServer.Components.WalletNav
{
public class WalletNav : ViewComponent
{
private readonly BTCPayWalletProvider _walletProvider;
private readonly PaymentMethodHandlerDictionary _handlers;
private readonly UIWalletsController _walletsController;
private readonly CurrencyNameTable _currencies;
private readonly BTCPayNetworkProvider _networkProvider;
private readonly RateFetcher _rateFetcher;
public WalletNav(
BTCPayWalletProvider walletProvider,
PaymentMethodHandlerDictionary handlers,
BTCPayNetworkProvider networkProvider,
UIWalletsController walletsController,
CurrencyNameTable currencies,
RateFetcher rateFetcher)
{
_walletProvider = walletProvider;
_handlers = handlers;
_networkProvider = networkProvider;
_walletsController = walletsController;
_currencies = currencies;
_rateFetcher = rateFetcher;
}
public async Task<IViewComponentResult> InvokeAsync(WalletId walletId)
{
var store = ViewContext.HttpContext.GetStoreData();
var network = _networkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode);
var wallet = _walletProvider.GetWallet(network);
var defaultCurrency = store.GetStoreBlob().DefaultCurrency;
var derivation = store.GetDerivationSchemeSettings(_handlers, walletId.CryptoCode);
var balance = await wallet.GetBalance(derivation?.AccountDerivation) switch
{
{ Available: null, Total: var total } => total,
{ Available: var available } => available
};
var vm = new WalletNavViewModel
{
WalletId = walletId,
Network = network,
Balance = balance.ShowMoney(network),
DefaultCurrency = defaultCurrency,
Label = derivation?.Label ?? $"{store.StoreName} {walletId.CryptoCode} Wallet"
};
if (defaultCurrency != network.CryptoCode)
{
var rule = store.GetStoreBlob().GetRateRules(_networkProvider)?.GetRuleFor(new Rating.CurrencyPair(network.CryptoCode, defaultCurrency));
var bid = rule is null ? null : (await _rateFetcher.FetchRate(rule, new StoreIdRateContext(walletId.StoreId), HttpContext.RequestAborted)).BidAsk?.Bid;
if (bid is decimal b)
{
var currencyData = _currencies.GetCurrencyData(defaultCurrency, true);
vm.BalanceDefaultCurrency = (balance.GetValue(network) * b).ShowMoney(currencyData.Divisibility);
}
}
return View(vm);
}
}
}