From 1672bb6e74cf39debf1e1eb837269f6634d8284f Mon Sep 17 00:00:00 2001 From: Steven Barclay Date: Sat, 11 Mar 2023 09:44:15 +0800 Subject: [PATCH 1/2] Add missing segwit BSQ keychain path to wallet info Add the new account path "44'/142'/1'" for segwit BSQ to the wallet info view, which was missed from PR #5109 making the wallet & UI changes to implement segwit BSQ. Also format the paths from the constants defined in 'BisqKeyChainGroupStructure', instead of using string literals, so that they are only defined in one place. (Though it is extremely unlikely the paths would ever change.) --- .../content/walletinfo/WalletInfoView.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java b/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java index d1ac7c584ea..3560e65ea07 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java @@ -25,6 +25,7 @@ import bisq.desktop.util.Layout; import bisq.core.btc.listeners.BalanceListener; +import bisq.core.btc.setup.BisqKeyChainGroupStructure; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.WalletService; @@ -38,16 +39,21 @@ import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; +import org.bitcoinj.crypto.ChildNumber; import org.bitcoinj.script.Script; import org.bitcoinj.wallet.DeterministicKeyChain; import javax.inject.Inject; import javax.inject.Named; +import com.google.common.base.Joiner; + import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; +import java.util.List; + import static bisq.desktop.util.FormBuilder.addButtonAfterGroup; import static bisq.desktop.util.FormBuilder.addMultilineLabel; import static bisq.desktop.util.FormBuilder.addTitledGroupBg; @@ -104,9 +110,14 @@ public void initialize() { addTitledGroupBg(root, ++gridRow, 4, Res.get("account.menu.walletInfo.path.headLine"), Layout.GROUP_DISTANCE); addMultilineLabel(root, gridRow, Res.get("account.menu.walletInfo.path.info"), Layout.FIRST_ROW_AND_GROUP_DISTANCE, Double.MAX_VALUE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BTC", "legacy"), "44'/0'/0'", -Layout.FLOATING_LABEL_DISTANCE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BTC", "segwit"), "44'/0'/1'", -Layout.FLOATING_LABEL_DISTANCE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BSQ", ""), "44'/142'/0'", -Layout.FLOATING_LABEL_DISTANCE); + addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BTC", "legacy"), + formatAccountPath(BisqKeyChainGroupStructure.BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); + addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BTC", "segwit"), + formatAccountPath(BisqKeyChainGroupStructure.BIP44_BTC_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); + addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BSQ", "legacy"), + formatAccountPath(BisqKeyChainGroupStructure.BIP44_BSQ_NON_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); + addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BSQ", "segwit"), + formatAccountPath(BisqKeyChainGroupStructure.BIP44_BSQ_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); openDetailsButton = addButtonAfterGroup(root, ++gridRow, Res.get("account.menu.walletInfo.openDetails")); @@ -124,6 +135,10 @@ public void onBalanceChanged(Coin balanceAsCoin, Transaction tx) { }; } + private String formatAccountPath(List path) { + return Joiner.on('/').join(path).replace('H', '\''); + } + @Override protected void activate() { @@ -170,6 +185,4 @@ private void updateBalances(WalletService walletService) { bsqTextField.setText(bsqFormatter.formatCoinWithCode(walletService.getBalance(ESTIMATED_SPENDABLE))); } } - } - From 4b2c7b15c476b5354cb82659769d8a066e857cff Mon Sep 17 00:00:00 2001 From: Steven Barclay Date: Sat, 11 Mar 2023 15:03:24 +0800 Subject: [PATCH 2/2] Iterate over wallet keychains instead of using hard coded BIP32 paths Add private method 'WalletInfoView.addAccountPaths', similar to the method 'addXpubKeys', to iterate over the active wallet keychains, formatting & displaying the derivation paths, instead of using the 4 constants defined in BisqKeyChainGroupStructure. Also simplify the code slightly by updating the 'gridRow' field directly instead of passing it as a method argument. --- .../content/walletinfo/WalletInfoView.java | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java b/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java index 3560e65ea07..53d75d21c64 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/walletinfo/WalletInfoView.java @@ -25,7 +25,6 @@ import bisq.desktop.util.Layout; import bisq.core.btc.listeners.BalanceListener; -import bisq.core.btc.setup.BisqKeyChainGroupStructure; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.WalletService; @@ -103,23 +102,15 @@ public void initialize() { bsqTextField = addTopLabelTextField(root, ++gridRow, "BSQ", -Layout.FLOATING_LABEL_DISTANCE).second; addTitledGroupBg(root, ++gridRow, 4, Res.get("account.menu.walletInfo.xpub.headLine"), Layout.GROUP_DISTANCE); - addXpubKeys(btcWalletService, "BTC", gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE); - ++gridRow; // update gridRow - addXpubKeys(bsqWalletService, "BSQ", ++gridRow, -Layout.FLOATING_LABEL_DISTANCE); - ++gridRow; // update gridRow - - addTitledGroupBg(root, ++gridRow, 4, Res.get("account.menu.walletInfo.path.headLine"), Layout.GROUP_DISTANCE); - addMultilineLabel(root, gridRow, Res.get("account.menu.walletInfo.path.info"), Layout.FIRST_ROW_AND_GROUP_DISTANCE, Double.MAX_VALUE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BTC", "legacy"), - formatAccountPath(BisqKeyChainGroupStructure.BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BTC", "segwit"), - formatAccountPath(BisqKeyChainGroupStructure.BIP44_BTC_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BSQ", "legacy"), - formatAccountPath(BisqKeyChainGroupStructure.BIP44_BSQ_NON_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); - addTopLabelTextField(root, ++gridRow, Res.get("account.menu.walletInfo.walletSelector", "BSQ", "segwit"), - formatAccountPath(BisqKeyChainGroupStructure.BIP44_BSQ_SEGWIT_ACCOUNT_PATH), -Layout.FLOATING_LABEL_DISTANCE); - - openDetailsButton = addButtonAfterGroup(root, ++gridRow, Res.get("account.menu.walletInfo.openDetails")); + addXpubKeys(btcWalletService, "BTC", Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addXpubKeys(bsqWalletService, "BSQ", -Layout.FLOATING_LABEL_DISTANCE); + + addTitledGroupBg(root, gridRow, 4, Res.get("account.menu.walletInfo.path.headLine"), Layout.GROUP_DISTANCE); + addMultilineLabel(root, gridRow++, Res.get("account.menu.walletInfo.path.info"), Layout.FIRST_ROW_AND_GROUP_DISTANCE, Double.MAX_VALUE); + addAccountPaths(btcWalletService, "BTC"); + addAccountPaths(bsqWalletService, "BSQ"); + + openDetailsButton = addButtonAfterGroup(root, gridRow, Res.get("account.menu.walletInfo.openDetails")); btcWalletBalanceListener = new BalanceListener() { @Override @@ -135,10 +126,6 @@ public void onBalanceChanged(Coin balanceAsCoin, Transaction tx) { }; } - private String formatAccountPath(List path) { - return Joiner.on('/').join(path).replace('H', '\''); - } - @Override protected void activate() { @@ -163,21 +150,32 @@ protected void deactivate() { openDetailsButton.setOnAction(null); } - private void addXpubKeys(WalletService walletService, String currency, int gridRow, double top) { - int row = gridRow; + private void addXpubKeys(WalletService walletService, String currency, double top) { double topDist = top; for (DeterministicKeyChain chain : walletService.getWallet().getActiveKeyChains()) { Script.ScriptType outputScriptType = chain.getOutputScriptType(); String type = outputScriptType == Script.ScriptType.P2WPKH ? "segwit" : "legacy"; String key = chain.getWatchingKey().serializePubB58(Config.baseCurrencyNetworkParameters(), outputScriptType); - addTopLabelTextField(root, row, - Res.get("account.menu.walletInfo.walletSelector", currency, type), + addTopLabelTextField(root, gridRow++, Res.get("account.menu.walletInfo.walletSelector", currency, type), key, topDist); - row++; topDist = -Layout.FLOATING_LABEL_DISTANCE; } } + private void addAccountPaths(WalletService walletService, String currency) { + for (DeterministicKeyChain chain : walletService.getWallet().getActiveKeyChains()) { + Script.ScriptType outputScriptType = chain.getOutputScriptType(); + String type = outputScriptType == Script.ScriptType.P2WPKH ? "segwit" : "legacy"; + String path = formatAccountPath(chain.getAccountPath()); + addTopLabelTextField(root, gridRow++, Res.get("account.menu.walletInfo.walletSelector", currency, type), + path, -Layout.FLOATING_LABEL_DISTANCE); + } + } + + private String formatAccountPath(List path) { + return Joiner.on('/').join(path).replace('H', '\''); + } + private void updateBalances(WalletService walletService) { if (walletService instanceof BtcWalletService) { btcTextField.setText(btcFormatter.formatCoinWithCode(walletService.getBalance(ESTIMATED_SPENDABLE)));