mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Disable cold wallet creation by default
This commit is contained in:
@@ -43,13 +43,13 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}
|
}
|
||||||
|
|
||||||
var canUseHotWallet = await CanUseHotWallet();
|
var canUseHotWallet = await CanUseHotWallet();
|
||||||
if (request.SavePrivateKeys && !canUseHotWallet.HotWallet)
|
if (request.SavePrivateKeys && !canUseHotWallet.CanCreateHotWallet)
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(request.SavePrivateKeys),
|
ModelState.AddModelError(nameof(request.SavePrivateKeys),
|
||||||
"This instance forbids non-admins from having a hot wallet for your store.");
|
"This instance forbids non-admins from having a hot wallet for your store.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.ImportKeysToRPC && !canUseHotWallet.RPCImport)
|
if (request.ImportKeysToRPC && !canUseHotWallet.CanRPCImport)
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(request.ImportKeysToRPC),
|
ModelState.AddModelError(nameof(request.ImportKeysToRPC),
|
||||||
"This instance forbids non-admins from having importing the wallet addresses/keys to the underlying node.");
|
"This instance forbids non-admins from having importing the wallet addresses/keys to the underlying node.");
|
||||||
@@ -120,7 +120,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<(bool HotWallet, bool RPCImport)> CanUseHotWallet()
|
private async Task<WalletCreationPermissions> CanUseHotWallet()
|
||||||
{
|
{
|
||||||
return await _authorizationService.CanUseHotWallet(PoliciesSettings, User);
|
return await _authorizationService.CanUseHotWallet(PoliciesSettings, User);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}
|
}
|
||||||
|
|
||||||
//This API is only meant for hot wallet usage for now. We can expand later when we allow PSBT manipulation.
|
//This API is only meant for hot wallet usage for now. We can expand later when we allow PSBT manipulation.
|
||||||
if (!(await CanUseHotWallet()).HotWallet)
|
if (!(await CanUseHotWallet()).CanCreateHotWallet)
|
||||||
{
|
{
|
||||||
return this.CreateAPIError(503, "not-available",
|
return this.CreateAPIError(503, "not-available",
|
||||||
$"You need to allow non-admins to use hotwallets for their stores (in /server/policies)");
|
$"You need to allow non-admins to use hotwallets for their stores (in /server/policies)");
|
||||||
@@ -802,7 +802,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<(bool HotWallet, bool RPCImport)> CanUseHotWallet()
|
private async Task<WalletCreationPermissions> CanUseHotWallet()
|
||||||
{
|
{
|
||||||
return await _authorizationService.CanUseHotWallet(PoliciesSettings, User);
|
return await _authorizationService.CanUseHotWallet(PoliciesSettings, User);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,10 +54,9 @@ public partial class UIStoresController
|
|||||||
return checkResult;
|
return checkResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (hotWallet, rpcImport) = await CanUseHotWallet();
|
var perm = await CanUseHotWallet();
|
||||||
vm.Network = network;
|
vm.Network = network;
|
||||||
vm.CanUseHotWallet = hotWallet;
|
vm.SetPermission(perm);
|
||||||
vm.CanUseRPCImport = rpcImport;
|
|
||||||
vm.SupportTaproot = network.NBitcoinNetwork.Consensus.SupportTaproot;
|
vm.SupportTaproot = network.NBitcoinNetwork.Consensus.SupportTaproot;
|
||||||
vm.SupportSegwit = network.NBitcoinNetwork.Consensus.SupportSegwit;
|
vm.SupportSegwit = network.NBitcoinNetwork.Consensus.SupportSegwit;
|
||||||
|
|
||||||
@@ -218,14 +217,13 @@ public partial class UIStoresController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isHotWallet = vm.Method == WalletSetupMethod.HotWallet;
|
var isHotWallet = vm.Method == WalletSetupMethod.HotWallet;
|
||||||
var (hotWallet, rpcImport) = await CanUseHotWallet();
|
var isColdWallet = vm.Method == WalletSetupMethod.WatchOnly;
|
||||||
if (isHotWallet && !hotWallet)
|
var perm = await CanUseHotWallet();
|
||||||
{
|
if (isHotWallet && !perm.CanCreateHotWallet)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
if (isColdWallet && !perm.CanCreateColdWallet)
|
||||||
|
return NotFound();
|
||||||
vm.CanUseHotWallet = hotWallet;
|
vm.SetPermission(perm);
|
||||||
vm.CanUseRPCImport = rpcImport;
|
|
||||||
vm.SupportTaproot = network.NBitcoinNetwork.Consensus.SupportTaproot;
|
vm.SupportTaproot = network.NBitcoinNetwork.Consensus.SupportTaproot;
|
||||||
vm.SupportSegwit = network.NBitcoinNetwork.Consensus.SupportSegwit;
|
vm.SupportSegwit = network.NBitcoinNetwork.Consensus.SupportSegwit;
|
||||||
vm.Network = network;
|
vm.Network = network;
|
||||||
@@ -236,7 +234,7 @@ public partial class UIStoresController
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var canUsePayJoin = hotWallet && isHotWallet && network.SupportPayJoin;
|
var canUsePayJoin = perm.CanCreateHotWallet && isHotWallet && network.SupportPayJoin;
|
||||||
vm.SetupRequest = new WalletSetupRequest
|
vm.SetupRequest = new WalletSetupRequest
|
||||||
{
|
{
|
||||||
SavePrivateKeys = isHotWallet,
|
SavePrivateKeys = isHotWallet,
|
||||||
@@ -260,8 +258,10 @@ public partial class UIStoresController
|
|||||||
return checkResult;
|
return checkResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (hotWallet, rpcImport) = await CanUseHotWallet();
|
var perm = await CanUseHotWallet();
|
||||||
if (!hotWallet && request.SavePrivateKeys || !rpcImport && request.ImportKeysToRPC)
|
if ((!perm.CanCreateHotWallet && request.SavePrivateKeys) ||
|
||||||
|
(!perm.CanRPCImport && request.ImportKeysToRPC) ||
|
||||||
|
(!perm.CanCreateColdWallet && !request.SavePrivateKeys))
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
@@ -279,12 +279,10 @@ public partial class UIStoresController
|
|||||||
Source = isImport ? "SeedImported" : "NBXplorerGenerated",
|
Source = isImport ? "SeedImported" : "NBXplorerGenerated",
|
||||||
IsHotWallet = isImport ? request.SavePrivateKeys : method == WalletSetupMethod.HotWallet,
|
IsHotWallet = isImport ? request.SavePrivateKeys : method == WalletSetupMethod.HotWallet,
|
||||||
DerivationSchemeFormat = "BTCPay",
|
DerivationSchemeFormat = "BTCPay",
|
||||||
CanUseHotWallet = hotWallet,
|
|
||||||
CanUseRPCImport = rpcImport,
|
|
||||||
SupportTaproot = network.NBitcoinNetwork.Consensus.SupportTaproot,
|
SupportTaproot = network.NBitcoinNetwork.Consensus.SupportTaproot,
|
||||||
SupportSegwit = network.NBitcoinNetwork.Consensus.SupportSegwit
|
SupportSegwit = network.NBitcoinNetwork.Consensus.SupportSegwit
|
||||||
};
|
};
|
||||||
|
vm.SetPermission(perm);
|
||||||
if (isImport && string.IsNullOrEmpty(request.ExistingMnemonic))
|
if (isImport && string.IsNullOrEmpty(request.ExistingMnemonic))
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(request.ExistingMnemonic), StringLocalizer["Please provide your existing seed"]);
|
ModelState.AddModelError(nameof(request.ExistingMnemonic), StringLocalizer["Please provide your existing seed"]);
|
||||||
@@ -404,7 +402,7 @@ public partial class UIStoresController
|
|||||||
|
|
||||||
var storeBlob = store.GetStoreBlob();
|
var storeBlob = store.GetStoreBlob();
|
||||||
var excludeFilters = storeBlob.GetExcludedPaymentMethods();
|
var excludeFilters = storeBlob.GetExcludedPaymentMethods();
|
||||||
(bool canUseHotWallet, bool rpcImport) = await CanUseHotWallet();
|
var perm = await CanUseHotWallet();
|
||||||
var client = _explorerProvider.GetExplorerClient(network);
|
var client = _explorerProvider.GetExplorerClient(network);
|
||||||
|
|
||||||
var handler = _handlers.GetBitcoinHandler(cryptoCode);
|
var handler = _handlers.GetBitcoinHandler(cryptoCode);
|
||||||
@@ -426,7 +424,7 @@ public partial class UIStoresController
|
|||||||
Label = derivation.Label,
|
Label = derivation.Label,
|
||||||
SelectedSigningKey = derivation.SigningKey?.ToString(),
|
SelectedSigningKey = derivation.SigningKey?.ToString(),
|
||||||
NBXSeedAvailable = derivation.IsHotWallet &&
|
NBXSeedAvailable = derivation.IsHotWallet &&
|
||||||
canUseHotWallet &&
|
perm.CanCreateHotWallet &&
|
||||||
!string.IsNullOrEmpty(await client.GetMetadataAsync<string>(derivation.AccountDerivation,
|
!string.IsNullOrEmpty(await client.GetMetadataAsync<string>(derivation.AccountDerivation,
|
||||||
WellknownMetadataKeys.MasterHDKey)),
|
WellknownMetadataKeys.MasterHDKey)),
|
||||||
AccountKeys = (derivation.AccountKeySettings ?? [])
|
AccountKeys = (derivation.AccountKeySettings ?? [])
|
||||||
@@ -438,9 +436,9 @@ public partial class UIStoresController
|
|||||||
}).ToList(),
|
}).ToList(),
|
||||||
Config = ProtectString(JToken.FromObject(derivation, handler.Serializer).ToString()),
|
Config = ProtectString(JToken.FromObject(derivation, handler.Serializer).ToString()),
|
||||||
PayJoinEnabled = storeBlob.PayJoinEnabled,
|
PayJoinEnabled = storeBlob.PayJoinEnabled,
|
||||||
CanUsePayJoin = canUseHotWallet && network.SupportPayJoin && derivation.IsHotWallet,
|
CanUsePayJoin = perm.CanCreateHotWallet && network.SupportPayJoin && derivation.IsHotWallet,
|
||||||
CanUseHotWallet = canUseHotWallet,
|
CanUseHotWallet = perm.CanCreateHotWallet,
|
||||||
CanUseRPCImport = rpcImport,
|
CanUseRPCImport = perm.CanRPCImport,
|
||||||
StoreName = store.StoreName,
|
StoreName = store.StoreName,
|
||||||
CanSetupMultiSig = (derivation.AccountKeySettings ?? []).Length > 1,
|
CanSetupMultiSig = (derivation.AccountKeySettings ?? []).Length > 1,
|
||||||
IsMultiSigOnServer = derivation.IsMultiSigOnServer,
|
IsMultiSigOnServer = derivation.IsMultiSigOnServer,
|
||||||
@@ -589,11 +587,8 @@ public partial class UIStoresController
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
(bool canUseHotWallet, bool _) = await CanUseHotWallet();
|
if (!(await CanUseHotWallet()).CanCreateHotWallet)
|
||||||
if (!canUseHotWallet)
|
|
||||||
{
|
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
|
||||||
|
|
||||||
var client = _explorerProvider.GetExplorerClient(network);
|
var client = _explorerProvider.GetExplorerClient(network);
|
||||||
if (await GetSeed(client, derivation) != null)
|
if (await GetSeed(client, derivation) != null)
|
||||||
@@ -753,7 +748,7 @@ public partial class UIStoresController
|
|||||||
!string.IsNullOrEmpty(seed) ? seed : null;
|
!string.IsNullOrEmpty(seed) ? seed : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<(bool HotWallet, bool RPCImport)> CanUseHotWallet()
|
private async Task<WalletCreationPermissions> CanUseHotWallet()
|
||||||
{
|
{
|
||||||
return await _authorizationService.CanUseHotWallet(_policiesSettings, User);
|
return await _authorizationService.CanUseHotWallet(_policiesSettings, User);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -795,7 +795,7 @@ namespace BTCPayServer.Controllers
|
|||||||
private async Task<bool> CanUseHotWallet()
|
private async Task<bool> CanUseHotWallet()
|
||||||
{
|
{
|
||||||
var policies = await _settingsRepository.GetSettingAsync<PoliciesSettings>();
|
var policies = await _settingsRepository.GetSettingAsync<PoliciesSettings>();
|
||||||
return (await _authorizationService.CanUseHotWallet(policies, User)).HotWallet;
|
return (await _authorizationService.CanUseHotWallet(policies, User)).CanCreateHotWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{walletId}/send")]
|
[HttpGet("{walletId}/send")]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#nullable enable
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
@@ -9,6 +10,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
|
|
||||||
namespace BTCPayServer
|
namespace BTCPayServer
|
||||||
{
|
{
|
||||||
|
public record WalletCreationPermissions(bool CanCreateHotWallet, bool CanCreateColdWallet, bool CanRPCImport);
|
||||||
public static class AuthorizationExtensions
|
public static class AuthorizationExtensions
|
||||||
{
|
{
|
||||||
public static async Task<bool> CanModifyStore(this IAuthorizationService authorizationService, ClaimsPrincipal user)
|
public static async Task<bool> CanModifyStore(this IAuthorizationService authorizationService, ClaimsPrincipal user)
|
||||||
@@ -16,24 +18,26 @@ namespace BTCPayServer
|
|||||||
return (await authorizationService.AuthorizeAsync(user, null,
|
return (await authorizationService.AuthorizeAsync(user, null,
|
||||||
new PolicyRequirement(Policies.CanModifyStoreSettings))).Succeeded;
|
new PolicyRequirement(Policies.CanModifyStoreSettings))).Succeeded;
|
||||||
}
|
}
|
||||||
public static async Task<(bool HotWallet, bool RPCImport)> CanUseHotWallet(
|
public static async Task<WalletCreationPermissions> CanUseHotWallet(
|
||||||
this IAuthorizationService authorizationService,
|
this IAuthorizationService authorizationService,
|
||||||
PoliciesSettings policiesSettings,
|
PoliciesSettings? policiesSettings,
|
||||||
ClaimsPrincipal user)
|
ClaimsPrincipal user)
|
||||||
{
|
{
|
||||||
if (!user.Identity.IsAuthenticated)
|
if (user.Identity?.IsAuthenticated is not true)
|
||||||
return (false, false);
|
return new(false, false, false);
|
||||||
var claimUser = user.Identity as ClaimsIdentity;
|
var claimUser = user.Identity as ClaimsIdentity;
|
||||||
if (claimUser is null)
|
if (claimUser is null)
|
||||||
return (false, false);
|
return new(false, false, false);
|
||||||
|
|
||||||
bool isAdmin = false;
|
bool isAdmin = false;
|
||||||
if (claimUser.AuthenticationType == AuthenticationSchemes.Cookie)
|
if (claimUser.AuthenticationType == AuthenticationSchemes.Cookie)
|
||||||
isAdmin = user.IsInRole(Roles.ServerAdmin);
|
isAdmin = user.IsInRole(Roles.ServerAdmin);
|
||||||
else if (claimUser.AuthenticationType == GreenfieldConstants.AuthenticationType)
|
else if (claimUser.AuthenticationType == GreenfieldConstants.AuthenticationType)
|
||||||
isAdmin = (await authorizationService.AuthorizeAsync(user, Policies.CanModifyServerSettings)).Succeeded;
|
isAdmin = (await authorizationService.AuthorizeAsync(user, Policies.CanModifyServerSettings)).Succeeded;
|
||||||
return isAdmin ? (true, true) :
|
return isAdmin ? new(true, true, true) :
|
||||||
(policiesSettings?.AllowHotWalletForAll is true, policiesSettings?.AllowHotWalletRPCImportForAll is true);
|
new(policiesSettings?.AllowHotWalletForAll is true,
|
||||||
|
policiesSettings?.AllowCreateColdWalletForAll is true,
|
||||||
|
policiesSettings?.AllowHotWalletRPCImportForAll is true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
public BTCPayNetwork Network { get; set; }
|
public BTCPayNetwork Network { get; set; }
|
||||||
[Display(Name = "Can use hot wallet")]
|
[Display(Name = "Can use hot wallet")]
|
||||||
public bool CanUseHotWallet { get; set; }
|
public bool CanUseHotWallet { get; set; }
|
||||||
|
[Display(Name = "Can create a new cold wallet")]
|
||||||
|
public bool CanCreateNewColdWallet { get; set; }
|
||||||
[Display(Name = "Can use RPC import")]
|
[Display(Name = "Can use RPC import")]
|
||||||
public bool CanUseRPCImport { get; set; }
|
public bool CanUseRPCImport { get; set; }
|
||||||
public bool SupportSegwit { get; set; }
|
public bool SupportSegwit { get; set; }
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
|
|
||||||
namespace BTCPayServer.Models.StoreViewModels
|
namespace BTCPayServer.Models.StoreViewModels
|
||||||
{
|
{
|
||||||
public enum WalletSetupMethod
|
public enum WalletSetupMethod
|
||||||
@@ -34,5 +37,21 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
WalletSetupMethod.WatchOnly => "GenerateWallet",
|
WalletSetupMethod.WatchOnly => "GenerateWallet",
|
||||||
_ => "SetupWallet"
|
_ => "SetupWallet"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal void SetPermission(WalletCreationPermissions perm)
|
||||||
|
{
|
||||||
|
this.CanCreateNewColdWallet = perm.CanCreateColdWallet;
|
||||||
|
this.CanUseHotWallet = perm.CanCreateHotWallet;
|
||||||
|
this.CanUseRPCImport = perm.CanRPCImport;
|
||||||
|
}
|
||||||
|
public void SetViewData(ViewDataDictionary ViewData)
|
||||||
|
{
|
||||||
|
ViewData.Add(nameof(CanUseHotWallet), CanUseHotWallet);
|
||||||
|
ViewData.Add(nameof(CanCreateNewColdWallet), CanCreateNewColdWallet);
|
||||||
|
ViewData.Add(nameof(CanUseRPCImport), CanUseRPCImport);
|
||||||
|
ViewData.Add(nameof(SupportSegwit), SupportSegwit);
|
||||||
|
ViewData.Add(nameof(SupportTaproot), SupportTaproot);
|
||||||
|
ViewData.Add(nameof(Method), Method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ namespace BTCPayServer.Services
|
|||||||
|
|
||||||
[Display(Name = "Non-admins can create Hot Wallets for their Store")]
|
[Display(Name = "Non-admins can create Hot Wallets for their Store")]
|
||||||
public bool AllowHotWalletForAll { get; set; }
|
public bool AllowHotWalletForAll { get; set; }
|
||||||
|
[Display(Name = "Non-admins can create Cold Wallets for their Store")]
|
||||||
|
public bool AllowCreateColdWalletForAll { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Non-admins can import Hot Wallets for their Store")]
|
[Display(Name = "Non-admins can import Hot Wallets for their Store")]
|
||||||
public bool AllowHotWalletRPCImportForAll { get; set; }
|
public bool AllowHotWalletRPCImportForAll { get; set; }
|
||||||
|
|||||||
@@ -120,6 +120,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-flex my-3">
|
||||||
|
<input asp-for="AllowCreateColdWalletForAll" type="checkbox" class="btcpay-toggle me-3" />
|
||||||
|
<div>
|
||||||
|
<label asp-for="AllowCreateColdWalletForAll" class="form-check-label"></label>
|
||||||
|
<span asp-validation-for="AllowCreateColdWalletForAll" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="d-flex my-3">
|
<div class="d-flex my-3">
|
||||||
<input asp-for="AllowHotWalletRPCImportForAll" type="checkbox" class="btcpay-toggle me-3"/>
|
<input asp-for="AllowHotWalletRPCImportForAll" type="checkbox" class="btcpay-toggle me-3"/>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -4,11 +4,7 @@
|
|||||||
var title = isHotWallet ? StringLocalizer["Create {0} Hot Wallet", Model.CryptoCode] : StringLocalizer["Create {0} Watch-Only Wallet", Model.CryptoCode];
|
var title = isHotWallet ? StringLocalizer["Create {0} Hot Wallet", Model.CryptoCode] : StringLocalizer["Create {0} Watch-Only Wallet", Model.CryptoCode];
|
||||||
Layout = "_LayoutWalletSetup";
|
Layout = "_LayoutWalletSetup";
|
||||||
ViewData.SetActivePage(StoreNavPages.OnchainSettings, title, $"{Context.GetStoreData().Id}-{Model.CryptoCode}");
|
ViewData.SetActivePage(StoreNavPages.OnchainSettings, title, $"{Context.GetStoreData().Id}-{Model.CryptoCode}");
|
||||||
ViewData.Add(nameof(Model.CanUseHotWallet), Model.CanUseHotWallet);
|
Model.SetViewData(ViewData);
|
||||||
ViewData.Add(nameof(Model.CanUseRPCImport), Model.CanUseRPCImport);
|
|
||||||
ViewData.Add(nameof(Model.SupportSegwit), Model.SupportSegwit);
|
|
||||||
ViewData.Add(nameof(Model.SupportTaproot), Model.SupportTaproot);
|
|
||||||
ViewData.Add(nameof(Model.Method), Model.Method);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@section Navbar {
|
@section Navbar {
|
||||||
|
|||||||
@@ -46,6 +46,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-group mt-4">
|
<div class="list-group mt-4">
|
||||||
|
@if (Model.CanCreateNewColdWallet)
|
||||||
|
{
|
||||||
<a asp-controller="UIStores" asp-action="GenerateWallet" asp-route-storeId="@Model.StoreId" asp-route-cryptoCode="@Model.CryptoCode" asp-route-method="@WalletSetupMethod.WatchOnly.ToString()" id="GenerateWatchonlyLink" class="list-group-item list-group-item-action">
|
<a asp-controller="UIStores" asp-action="GenerateWallet" asp-route-storeId="@Model.StoreId" asp-route-cryptoCode="@Model.CryptoCode" asp-route-method="@WalletSetupMethod.WatchOnly.ToString()" id="GenerateWatchonlyLink" class="list-group-item list-group-item-action">
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<vc:icon symbol="wallet-watchonly"/>
|
<vc:icon symbol="wallet-watchonly"/>
|
||||||
@@ -58,6 +60,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<vc:icon symbol="caret-right" />
|
<vc:icon symbol="caret-right" />
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="list-group-item text-muted">
|
||||||
|
<div class="image">
|
||||||
|
<vc:icon symbol="wallet-watchonly" />
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<h4 text-translate="true">Watch-only wallet</h4>
|
||||||
|
<p class="mb-0" text-translate="true">Please note that this instance does not support creating a new cold wallet for non-administrators. However, you can import one from other wallet software.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,7 @@
|
|||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
@if (Model.CanUseHotWallet)
|
@if (Model.CanUseHotWallet)
|
||||||
{
|
{
|
||||||
ViewData.Add(nameof(Model.CanUseHotWallet), Model.CanUseHotWallet);
|
Model.SetViewData(ViewData);
|
||||||
ViewData.Add(nameof(Model.CanUseRPCImport), Model.CanUseRPCImport);
|
|
||||||
ViewData.Add(nameof(Model.SupportSegwit), Model.SupportSegwit);
|
|
||||||
ViewData.Add(nameof(Model.SupportTaproot), Model.SupportTaproot);
|
|
||||||
ViewData.Add(nameof(Model.Method), Model.Method);
|
|
||||||
|
|
||||||
<partial name="_GenerateWalletForm" model="Model.SetupRequest" />
|
<partial name="_GenerateWalletForm" model="Model.SetupRequest" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user