mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 22:44:29 +01:00
Allow flexible derivation scheme for the store
This commit is contained in:
@@ -45,9 +45,9 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
await store.UpdateStore(StoreId, new StoreViewModel()
|
await store.UpdateStore(StoreId, new StoreViewModel()
|
||||||
{
|
{
|
||||||
ExtPubKey = extKey.Neuter().ToString() + "-[legacy]",
|
DerivationScheme = extKey.Neuter().ToString() + "-[legacy]",
|
||||||
SpeedPolicy = SpeedPolicy.MediumSpeed
|
SpeedPolicy = SpeedPolicy.MediumSpeed
|
||||||
});
|
}, "Save");
|
||||||
Assert.IsType<ViewResult>(await store.RequestPairing(pairingCode.ToString()));
|
Assert.IsType<ViewResult>(await store.RequestPairing(pairingCode.ToString()));
|
||||||
await store.Pair(pairingCode.ToString(), StoreId);
|
await store.Pair(pairingCode.ToString(), StoreId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Identity;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitpayClient;
|
using NBitpayClient;
|
||||||
|
using NBXplorer.DerivationStrategy;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -28,6 +29,7 @@ namespace BTCPayServer.Controllers
|
|||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
AccessTokenController tokenController,
|
AccessTokenController tokenController,
|
||||||
BTCPayWallet wallet,
|
BTCPayWallet wallet,
|
||||||
|
Network network,
|
||||||
IHostingEnvironment env)
|
IHostingEnvironment env)
|
||||||
{
|
{
|
||||||
_Repo = repo;
|
_Repo = repo;
|
||||||
@@ -36,7 +38,9 @@ namespace BTCPayServer.Controllers
|
|||||||
_TokenController = tokenController;
|
_TokenController = tokenController;
|
||||||
_Wallet = wallet;
|
_Wallet = wallet;
|
||||||
_Env = env;
|
_Env = env;
|
||||||
|
_Network = network;
|
||||||
}
|
}
|
||||||
|
Network _Network;
|
||||||
BTCPayWallet _Wallet;
|
BTCPayWallet _Wallet;
|
||||||
AccessTokenController _TokenController;
|
AccessTokenController _TokenController;
|
||||||
StoreRepository _Repo;
|
StoreRepository _Repo;
|
||||||
@@ -106,7 +110,7 @@ namespace BTCPayServer.Controllers
|
|||||||
vm.StoreName = store.StoreName;
|
vm.StoreName = store.StoreName;
|
||||||
vm.StoreWebsite = store.StoreWebsite;
|
vm.StoreWebsite = store.StoreWebsite;
|
||||||
vm.SpeedPolicy = store.SpeedPolicy;
|
vm.SpeedPolicy = store.SpeedPolicy;
|
||||||
vm.ExtPubKey = store.DerivationStrategy;
|
vm.DerivationScheme = store.DerivationStrategy;
|
||||||
vm.StatusMessage = StatusMessage;
|
vm.StatusMessage = StatusMessage;
|
||||||
return View(vm);
|
return View(vm);
|
||||||
}
|
}
|
||||||
@@ -114,7 +118,7 @@ namespace BTCPayServer.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
[Route("{storeId}")]
|
[Route("{storeId}")]
|
||||||
public async Task<IActionResult> UpdateStore(string storeId, StoreViewModel model)
|
public async Task<IActionResult> UpdateStore(string storeId, StoreViewModel model, string command)
|
||||||
{
|
{
|
||||||
if(!ModelState.IsValid)
|
if(!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
@@ -124,6 +128,8 @@ namespace BTCPayServer.Controllers
|
|||||||
if(store == null)
|
if(store == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
|
if(command == "Save")
|
||||||
|
{
|
||||||
bool needUpdate = false;
|
bool needUpdate = false;
|
||||||
if(store.SpeedPolicy != model.SpeedPolicy)
|
if(store.SpeedPolicy != model.SpeedPolicy)
|
||||||
{
|
{
|
||||||
@@ -141,17 +147,17 @@ namespace BTCPayServer.Controllers
|
|||||||
store.StoreWebsite = model.StoreWebsite;
|
store.StoreWebsite = model.StoreWebsite;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(store.DerivationStrategy != model.ExtPubKey)
|
if(store.DerivationStrategy != model.DerivationScheme)
|
||||||
{
|
{
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _Wallet.TrackAsync(model.ExtPubKey);
|
await _Wallet.TrackAsync(model.DerivationScheme);
|
||||||
store.DerivationStrategy = model.ExtPubKey;
|
store.DerivationStrategy = model.DerivationScheme;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(model.ExtPubKey), "Invalid Derivation Scheme");
|
ModelState.AddModelError(nameof(model.DerivationScheme), "Invalid Derivation Scheme");
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,6 +173,20 @@ namespace BTCPayServer.Controllers
|
|||||||
storeId = storeId
|
storeId = storeId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var facto = new DerivationStrategyFactory(_Network);
|
||||||
|
var scheme = facto.Parse(model.DerivationScheme);
|
||||||
|
var line = scheme.GetLineFor(DerivationFeature.Deposit);
|
||||||
|
|
||||||
|
for(int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
var address = line.Derive((uint)i);
|
||||||
|
model.AddressSamples.Add((line.Path.Derive((uint)i).ToString(), address.ScriptPubKey.GetDestinationAddress(_Network).ToString()));
|
||||||
|
}
|
||||||
|
return View(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{storeId}/Tokens")]
|
[Route("{storeId}/Tokens")]
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ExtPubKeyValidator]
|
[DerivationStrategyValidator]
|
||||||
public string ExtPubKey
|
public string DerivationScheme
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,11 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<(string KeyPath, string Address)> AddressSamples
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
} = new List<(string KeyPath, string Address)>();
|
||||||
|
|
||||||
public string StatusMessage
|
public string StatusMessage
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
using NBXplorer.DerivationStrategy;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
@@ -6,7 +7,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace BTCPayServer.Validations
|
namespace BTCPayServer.Validations
|
||||||
{
|
{
|
||||||
public class ExtPubKeyValidatorAttribute : ValidationAttribute
|
public class DerivationStrategyValidatorAttribute : ValidationAttribute
|
||||||
{
|
{
|
||||||
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
@@ -19,7 +20,7 @@ namespace BTCPayServer.Validations
|
|||||||
return new ValidationResult("No Network specified");
|
return new ValidationResult("No Network specified");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
new BitcoinExtPubKey((string)value, network);
|
new DerivationStrategyFactory(network).Parse((string)value);
|
||||||
return ValidationResult.Success;
|
return ValidationResult.Success;
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
@@ -36,11 +36,77 @@
|
|||||||
<span asp-validation-for="SpeedPolicy" class="text-danger"></span>
|
<span asp-validation-for="SpeedPolicy" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="ExtPubKey"></label>
|
<h5>Derivation Scheme</h5>
|
||||||
<input asp-for="ExtPubKey" class="form-control" />
|
@if(Model.AddressSamples.Count == 0)
|
||||||
<span asp-validation-for="ExtPubKey" class="text-danger"></span>
|
{
|
||||||
|
<span>The DerivationScheme represents the destination of the funds received by your invoice. It is generated by your wallet software. Please, verify that you are generating the right addresses by clicking on 'Check ExtPubKey'</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-default">Save</button>
|
<div class="form-group">
|
||||||
|
<input asp-for="DerivationScheme" class="form-control" />
|
||||||
|
<span asp-validation-for="DerivationScheme" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
@if(Model.AddressSamples.Count == 0)
|
||||||
|
{
|
||||||
|
<table class="table">
|
||||||
|
<thead class="thead-inverse">
|
||||||
|
<tr>
|
||||||
|
<th>Address type</th>
|
||||||
|
<th>Example</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>P2WPKH</td>
|
||||||
|
<td>xpub</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>P2SH-P2WPKH</td>
|
||||||
|
<td>xpub-[p2sh]</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>P2SH</td>
|
||||||
|
<td>xpub-[legacy]</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Multi-sig P2WSH</td>
|
||||||
|
<td>2-of-xpub1-xpub2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Multi-sig P2SH-P2WSH</td>
|
||||||
|
<td>2-of-xpub1-xpub2-[p2sh]</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Multi-sig P2SH</td>
|
||||||
|
<td>2-of-xpub1-xpub2-[legacy]</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<table class="table">
|
||||||
|
<thead class="thead-inverse">
|
||||||
|
<tr>
|
||||||
|
<th>Key path</th>
|
||||||
|
<th>Address</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach(var sample in Model.AddressSamples)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>@sample.KeyPath</td>
|
||||||
|
<td>@sample.Address</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<button name="command" type="submit" class="btn btn-success" value="Save">Save</button>
|
||||||
|
<button name="command" type="submit" class="btn btn-default" value="Check">Check ExtPubKey</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user