diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj
index 86ceb5e0e..679bebed2 100644
--- a/BTCPayServer/BTCPayServer.csproj
+++ b/BTCPayServer/BTCPayServer.csproj
@@ -125,6 +125,18 @@
$(IncludeRazorContentInPack)
+
+ $(IncludeRazorContentInPack)
+
+
+ $(IncludeRazorContentInPack)
+
+
+ $(IncludeRazorContentInPack)
+
+
+ $(IncludeRazorContentInPack)
+
diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs
index 861f51ac9..62d16df2e 100644
--- a/BTCPayServer/Controllers/StoresController.BTCLike.cs
+++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs
@@ -34,7 +34,7 @@ namespace BTCPayServer.Controllers
}
DerivationSchemeViewModel vm = new DerivationSchemeViewModel();
- vm.ServerUrl = GetStoreUrl(storeId);
+ vm.ServerUrl = WalletsController.GetLedgerWebsocketUrl(this.HttpContext, cryptoCode, null);
vm.CryptoCode = cryptoCode;
vm.RootKeyPath = network.GetRootKeyPath();
SetExistingValues(store, vm);
@@ -59,7 +59,7 @@ namespace BTCPayServer.Controllers
[Route("{storeId}/derivations/{cryptoCode}")]
public async Task AddDerivationScheme(string storeId, DerivationSchemeViewModel vm, string cryptoCode)
{
- vm.ServerUrl = GetStoreUrl(storeId);
+ vm.ServerUrl = WalletsController.GetLedgerWebsocketUrl(this.HttpContext, cryptoCode, null);
vm.CryptoCode = cryptoCode;
var store = HttpContext.GetStoreData();
if (store == null)
@@ -161,279 +161,5 @@ namespace BTCPayServer.Controllers
vm.Confirmation = true;
return View(vm);
}
-
-
- public class GetInfoResult
- {
- public int RecommendedSatoshiPerByte { get; set; }
- public double Balance { get; set; }
- }
-
- public class SendToAddressResult
- {
- public string TransactionId { get; set; }
- }
-
- [HttpGet]
- [Route("{storeId}/ws/ledger")]
- public async Task LedgerConnection(
- string storeId,
- string command,
- // getinfo
- string cryptoCode = null,
- // getxpub
- int account = 0,
- // sendtoaddress
- string destination = null, string amount = null, string feeRate = null, string substractFees = null
- )
- {
- if (!HttpContext.WebSockets.IsWebSocketRequest)
- return NotFound();
- var store = HttpContext.GetStoreData();
- if (store == null)
- return NotFound();
-
- var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
-
- using (var normalOperationTimeout = new CancellationTokenSource())
- using (var signTimeout = new CancellationTokenSource())
- {
- normalOperationTimeout.CancelAfter(TimeSpan.FromMinutes(30));
- var hw = new HardwareWalletService(webSocket);
- object result = null;
- try
- {
- BTCPayNetwork network = null;
- if (cryptoCode != null)
- {
- network = _NetworkProvider.GetNetwork(cryptoCode);
- if (network == null)
- throw new FormatException("Invalid value for crypto code");
- }
-
- BitcoinAddress destinationAddress = null;
- if (destination != null)
- {
- try
- {
- destinationAddress = BitcoinAddress.Create(destination, network.NBitcoinNetwork);
- }
- catch { }
- if (destinationAddress == null)
- throw new FormatException("Invalid value for destination");
- }
-
- FeeRate feeRateValue = null;
- if (feeRate != null)
- {
- try
- {
- feeRateValue = new FeeRate(Money.Satoshis(int.Parse(feeRate, CultureInfo.InvariantCulture)), 1);
- }
- catch { }
- if (feeRateValue == null || feeRateValue.FeePerK <= Money.Zero)
- throw new FormatException("Invalid value for fee rate");
- }
-
- Money amountBTC = null;
- if (amount != null)
- {
- try
- {
- amountBTC = Money.Parse(amount);
- }
- catch { }
- if (amountBTC == null || amountBTC <= Money.Zero)
- throw new FormatException("Invalid value for amount");
- }
-
- bool subsctractFeesValue = false;
- if (substractFees != null)
- {
- try
- {
- subsctractFeesValue = bool.Parse(substractFees);
- }
- catch { throw new FormatException("Invalid value for subtract fees"); }
- }
- if (command == "test")
- {
- result = await hw.Test(normalOperationTimeout.Token);
- }
- if (command == "getxpub")
- {
- var getxpubResult = await hw.GetExtPubKey(network, account, normalOperationTimeout.Token);
- result = getxpubResult;
- }
- if (command == "getinfo")
- {
- var strategy = GetDirectDerivationStrategy(store, network);
- var strategyBase = GetDerivationStrategy(store, network);
- if (strategy == null || await hw.GetKeyPath(network, strategy, normalOperationTimeout.Token) == null)
- {
- throw new Exception($"This store is not configured to use this ledger");
- }
-
- var feeProvider = _FeeRateProvider.CreateFeeProvider(network);
- var recommendedFees = feeProvider.GetFeeRateAsync();
- var balance = _WalletProvider.GetWallet(network).GetBalance(strategyBase);
- result = new GetInfoResult() { Balance = (double)(await balance).ToDecimal(MoneyUnit.BTC), RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi };
- }
-
- if (command == "sendtoaddress")
- {
- if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
- throw new Exception($"{network.CryptoCode}: not started or fully synched");
- var strategy = GetDirectDerivationStrategy(store, network);
- var strategyBase = GetDerivationStrategy(store, network);
- var wallet = _WalletProvider.GetWallet(network);
- var change = wallet.GetChangeAddressAsync(strategyBase);
-
- var unspentCoins = await wallet.GetUnspentCoins(strategyBase);
- var changeAddress = await change;
- var send = new[] { (
- destination: destinationAddress as IDestination,
- amount: amountBTC,
- substractFees: subsctractFeesValue) };
-
- foreach (var element in send)
- {
- if (element.destination == null)
- throw new ArgumentNullException(nameof(element.destination));
- if (element.amount == null)
- throw new ArgumentNullException(nameof(element.amount));
- if (element.amount <= Money.Zero)
- throw new ArgumentOutOfRangeException(nameof(element.amount), "The amount should be above zero");
- }
-
- var foundKeyPath = await hw.GetKeyPath(network, strategy, normalOperationTimeout.Token);
- if (foundKeyPath == null)
- {
- throw new HardwareWalletException($"This store is not configured to use this ledger");
- }
-
- TransactionBuilder builder = new TransactionBuilder();
- builder.StandardTransactionPolicy.MinRelayTxFee = summary.Status.BitcoinStatus.MinRelayTxFee;
- builder.SetConsensusFactory(network.NBitcoinNetwork);
- builder.AddCoins(unspentCoins.Select(c => c.Coin).ToArray());
-
- foreach (var element in send)
- {
- builder.Send(element.destination, element.amount);
- if (element.substractFees)
- builder.SubtractFees();
- }
- builder.SetChange(changeAddress.Item1);
-
- if (network.MinFee == null)
- {
- builder.SendEstimatedFees(feeRateValue);
- }
- else
- {
- var estimatedFee = builder.EstimateFees(feeRateValue);
- if (network.MinFee > estimatedFee)
- builder.SendFees(network.MinFee);
- else
- builder.SendEstimatedFees(feeRateValue);
- }
- builder.Shuffle();
- var unsigned = builder.BuildTransaction(false);
-
- var keypaths = new Dictionary