mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-19 05:33:31 +01:00
Vault: Allow user to pick the account number
This commit is contained in:
parent
ea5bd6d435
commit
50e7d8389c
@ -193,39 +193,63 @@ namespace BTCPayServer.Controllers
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "ask-xpubs":
|
||||
case "ask-xpub":
|
||||
if (await RequireDeviceUnlocking())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var askedXpub = JObject.Parse(await websocketHelper.NextMessageAsync(cancellationToken));
|
||||
var addressType = askedXpub["addressType"].Value<string>();
|
||||
var accountNumber = askedXpub["accountNumber"].Value<int>();
|
||||
JObject result = new JObject();
|
||||
var factory = network.NBXplorerNetwork.DerivationStrategyFactory;
|
||||
var keyPath = new KeyPath("84'").Derive(network.CoinType).Derive(0, true);
|
||||
BitcoinExtPubKey xpub = await device.GetXPubAsync(keyPath);
|
||||
if (fingerprint is null)
|
||||
{
|
||||
fingerprint = (await device.GetXPubAsync(new KeyPath("44'"), cancellationToken)).ExtPubKey.ParentFingerprint;
|
||||
}
|
||||
result["fingerprint"] = fingerprint.Value.ToString();
|
||||
var strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
|
||||
|
||||
DerivationStrategyBase strategy = null;
|
||||
KeyPath keyPath = null;
|
||||
BitcoinExtPubKey xpub = null;
|
||||
|
||||
if (!network.NBitcoinNetwork.Consensus.SupportSegwit && addressType != "legacy")
|
||||
{
|
||||
ScriptPubKeyType = ScriptPubKeyType.Segwit
|
||||
});
|
||||
AddDerivationSchemeToJson("segwit", result, keyPath, xpub, strategy);
|
||||
keyPath = new KeyPath("49'").Derive(network.CoinType).Derive(0, true);
|
||||
xpub = await device.GetXPubAsync(keyPath);
|
||||
strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
|
||||
await websocketHelper.Send("{ \"error\": \"segwit-notsupported\"}", cancellationToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addressType == "segwit")
|
||||
{
|
||||
ScriptPubKeyType = ScriptPubKeyType.SegwitP2SH
|
||||
});
|
||||
AddDerivationSchemeToJson("segwitWrapped", result, keyPath, xpub, strategy);
|
||||
keyPath = new KeyPath("44'").Derive(network.CoinType).Derive(0, true);
|
||||
xpub = await device.GetXPubAsync(keyPath);
|
||||
strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
|
||||
keyPath = new KeyPath("84'").Derive(network.CoinType).Derive(accountNumber, true);
|
||||
xpub = await device.GetXPubAsync(keyPath);
|
||||
strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
|
||||
{
|
||||
ScriptPubKeyType = ScriptPubKeyType.Segwit
|
||||
});
|
||||
}
|
||||
if (addressType == "segwitWrapped")
|
||||
{
|
||||
ScriptPubKeyType = ScriptPubKeyType.Legacy
|
||||
});
|
||||
AddDerivationSchemeToJson("legacy", result, keyPath, xpub, strategy);
|
||||
keyPath = new KeyPath("49'").Derive(network.CoinType).Derive(accountNumber, true);
|
||||
xpub = await device.GetXPubAsync(keyPath);
|
||||
strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
|
||||
{
|
||||
ScriptPubKeyType = ScriptPubKeyType.SegwitP2SH
|
||||
});
|
||||
}
|
||||
else if (addressType == "legacy")
|
||||
{
|
||||
keyPath = new KeyPath("44'").Derive(network.CoinType).Derive(accountNumber, true);
|
||||
xpub = await device.GetXPubAsync(keyPath);
|
||||
strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
|
||||
{
|
||||
ScriptPubKeyType = ScriptPubKeyType.Legacy
|
||||
});
|
||||
}
|
||||
result.Add(new JProperty("strategy", strategy.ToString()));
|
||||
result.Add(new JProperty("accountKey", xpub.ToString()));
|
||||
result.Add(new JProperty("keyPath", keyPath.ToString()));
|
||||
await websocketHelper.Send(result.ToString(), cancellationToken);
|
||||
break;
|
||||
case "ask-device":
|
||||
@ -296,15 +320,5 @@ namespace BTCPayServer.Controllers
|
||||
.FirstOrDefault(p => p.PaymentId.PaymentType == Payments.PaymentTypes.BTCLike && p.PaymentId.CryptoCode == walletId.CryptoCode);
|
||||
return paymentMethod;
|
||||
}
|
||||
|
||||
private void AddDerivationSchemeToJson(string propertyName, JObject result, KeyPath keyPath, BitcoinExtPubKey xpub, DerivationStrategyBase strategy)
|
||||
{
|
||||
result.Add(new JProperty(propertyName, new JObject()
|
||||
{
|
||||
new JProperty("strategy", strategy.ToString()),
|
||||
new JProperty("accountKey", xpub.ToString()),
|
||||
new JProperty("keyPath", keyPath.ToString()),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,22 +92,31 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>You may import from BTCPayServer Vault.</p>
|
||||
<div id="vaultPlaceholder"></div>
|
||||
<div class="form-group">
|
||||
<div id="vaultPlaceholder"></div>
|
||||
</div>
|
||||
<div id="vault-xpub" style="display:none;">
|
||||
<div class="form-group">
|
||||
<label for="addressType">Address type</label>
|
||||
<select name="addressType" class="form-control">
|
||||
<option value="segwit">Segwit (Recommended, cheapest transaction fee)</option>
|
||||
<option value="segwitWrapped">Segwit wrapped (less cheap but compatible with old wallets)</option>
|
||||
<option value="legacy">Legacy (Not recommended)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="accountNumber">Account</label>
|
||||
<select name="accountNumber" class="form-control">
|
||||
@for (int i = 0; i < 20; i++)
|
||||
{
|
||||
<option value="@i">@i</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
|
||||
<div id="vault-dropdown" style="display:none;" class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Select the type of address you want
|
||||
</button>
|
||||
<div class="dropdown-menu overflow-auto" style="max-height: 200px;">
|
||||
<a class="dropdown-item" href="#" id="vault-segwit">Segwit (Recommended, cheapest transaction fee)</a>
|
||||
<a class="dropdown-item" href="#" id="vault-segwitWrapped">Segwit wrapped (less cheap but compatible with old wallets)</a>
|
||||
<a class="dropdown-item" href="#" id="vault-legacy">Legacy (Not recommended)</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="vault-confirm" class="btn btn-primary" style="display:none;"></button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -112,20 +112,15 @@ $(document).ready(function () {
|
||||
ws_uri += "//" + loc.host;
|
||||
ws_uri += websocketPath;
|
||||
|
||||
function displayXPubs(xpubs) {
|
||||
$("#vault-dropdown").css("display", "block");
|
||||
$("#vault-dropdown .dropdown-item").click(function () {
|
||||
var id = $(this).attr('id').replace("vault-", "");
|
||||
var xpub = xpubs[id];
|
||||
$("#DerivationScheme").val(xpub.strategy);
|
||||
$("#RootFingerprint").val(xpubs.fingerprint);
|
||||
$("#AccountKey").val(xpub.accountKey);
|
||||
$("#Source").val("Vault");
|
||||
$("#DerivationSchemeFormat").val("BTCPay");
|
||||
$("#KeyPath").val(xpub.keyPath);
|
||||
$(".modal").modal('hide');
|
||||
$(".hw-fields").show();
|
||||
});
|
||||
function displayXPubs(xpub) {
|
||||
$("#DerivationScheme").val(xpub.strategy);
|
||||
$("#RootFingerprint").val(xpub.fingerprint);
|
||||
$("#AccountKey").val(xpub.accountKey);
|
||||
$("#Source").val("Vault");
|
||||
$("#DerivationSchemeFormat").val("BTCPay");
|
||||
$("#KeyPath").val(xpub.keyPath);
|
||||
$(".modal").modal('hide');
|
||||
$(".hw-fields").show();
|
||||
}
|
||||
|
||||
var vaultInit = false;
|
||||
@ -138,8 +133,8 @@ $(document).ready(function () {
|
||||
$("#vaultPlaceholder").html(html);
|
||||
|
||||
var vaultUI = new vaultui.VaultBridgeUI(ws_uri);
|
||||
if (await vaultUI.askForXPubs()) {
|
||||
displayXPubs(vaultUI.xpubs);
|
||||
if (await vaultUI.askForDevice() && await vaultUI.askForXPubs()) {
|
||||
displayXPubs(vaultUI.xpub);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -37,6 +37,7 @@ var vaultui = (function () {
|
||||
fetchingDevice: new VaultFeedback("?", "Fetching device...", "vault-feedback2", "fetching-device"),
|
||||
deviceFound: new VaultFeedback("ok", "Device found: {{0}}", "vault-feedback2", "device-selected"),
|
||||
fetchingXpubs: new VaultFeedback("?", "Fetching public keys...", "vault-feedback3", "fetching-xpubs"),
|
||||
askXpubs: new VaultFeedback("?", "Select your address type and account", "vault-feedback3", "fetching-xpubs"),
|
||||
fetchedXpubs: new VaultFeedback("ok", "Public keys successfully fetched.", "vault-feedback3", "xpubs-fetched"),
|
||||
unexpectedError: new VaultFeedback("failed", "An unexpected error happened.", "vault-feedback3", "unknown-error"),
|
||||
invalidNetwork: new VaultFeedback("failed", "The device is targetting a different chain.", "vault-feedback3", "invalid-network"),
|
||||
@ -69,7 +70,7 @@ var vaultui = (function () {
|
||||
*/
|
||||
this.psbt = null;
|
||||
|
||||
this.xpubs = null;
|
||||
this.xpub = null;
|
||||
/**
|
||||
* @param {VaultFeedback} feedback
|
||||
*/
|
||||
@ -172,8 +173,10 @@ var vaultui = (function () {
|
||||
this.askForXPubs = async function () {
|
||||
if (!await self.ensureConnectedToBackend())
|
||||
return false;
|
||||
self.bridge.socket.send("ask-xpub");
|
||||
var selectedXPubs = await self.getXpubSettings();
|
||||
self.bridge.socket.send(JSON.stringify(selectedXPubs));
|
||||
show(VaultFeedbacks.fetchingXpubs);
|
||||
self.bridge.socket.send("ask-xpubs");
|
||||
var json = await self.bridge.waitBackendMessage();
|
||||
if (json.hasOwnProperty("error")) {
|
||||
if (await needRetry(json))
|
||||
@ -181,10 +184,33 @@ var vaultui = (function () {
|
||||
return false;
|
||||
}
|
||||
show(VaultFeedbacks.fetchedXpubs);
|
||||
self.xpubs = json;
|
||||
self.xpub = json;
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Promise<{addressType:string, accountNumber:number}>}
|
||||
*/
|
||||
this.getXpubSettings = function () {
|
||||
show(VaultFeedbacks.askXpubs);
|
||||
$("#vault-xpub").css("display", "block");
|
||||
$("#vault-confirm").css("display", "block");
|
||||
$("#vault-confirm").text("Confirm");
|
||||
return new Promise(function (resolve, reject) {
|
||||
var pinCode = "";
|
||||
$("#vault-confirm").click(async function (e) {
|
||||
e.preventDefault();
|
||||
$("#vault-xpub").css("display", "none");
|
||||
$("#vault-confirm").css("display", "none");
|
||||
$(this).unbind();
|
||||
resolve({
|
||||
addressType: $("select[name=\"addressType\"]").val(),
|
||||
accountNumber: parseInt($("select[name=\"accountNumber\"]").val())
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
@ -195,7 +221,8 @@ var vaultui = (function () {
|
||||
$("#vault-confirm").text("Confirm the pin code");
|
||||
return new Promise(function (resolve, reject) {
|
||||
var pinCode = "";
|
||||
$("#vault-confirm").click(async function () {
|
||||
$("#vault-confirm").click(async function (e) {
|
||||
e.preventDefault();
|
||||
$("#pin-input").css("display", "none");
|
||||
$("#vault-confirm").css("display", "none");
|
||||
$(this).unbind();
|
||||
|
Loading…
Reference in New Issue
Block a user