implement changes to export addresses functionality

This commit is contained in:
Craig Raw 2021-04-06 09:27:51 +02:00
parent 6785bccf0e
commit 193f88b88f
7 changed files with 84 additions and 46 deletions

View file

@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.wallet;
import com.csvreader.CsvWriter;
import com.google.common.eventbus.Subscribe;
import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletNode;
import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.EventManager;
@ -20,10 +21,12 @@ import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
public class AddressesController extends WalletFormController implements Initializable {
private static final Logger log = LoggerFactory.getLogger(AddressesController.class);
public static final int DEFAULT_EXPORT_ADDRESSES_LENGTH = 250;
@FXML
private AddressTreeTable receiveTable;
@ -96,26 +99,36 @@ public class AddressesController extends WalletFormController implements Initial
}
public void exportReceiveAddresses(ActionEvent event) {
exportFile();
exportAddresses(KeyPurpose.RECEIVE);
}
private void exportFile() {
public void exportChangeAddresses(ActionEvent event) {
exportAddresses(KeyPurpose.CHANGE);
}
private void exportAddresses(KeyPurpose keyPurpose) {
Stage window = new Stage();
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Export Addresses File");
String extension = "txt";
fileChooser.setInitialFileName(getWalletForm().getWallet().getName() + "-addresses.txt");
fileChooser.setTitle("Export Addresses to CSV");
fileChooser.setInitialFileName(getWalletForm().getWallet().getName() + "-" + keyPurpose.name().toLowerCase() + "-addresses.txt");
Wallet copy = getWalletForm().getWallet().copy();
WalletNode purposeNode = copy.getNode(keyPurpose);
purposeNode.fillToIndex(Math.max(purposeNode.getChildren().size(), DEFAULT_EXPORT_ADDRESSES_LENGTH));
File file = fileChooser.showSaveDialog(window);
if(file != null) {
try(FileOutputStream outputStream = new FileOutputStream(file)) {
CsvWriter writer = new CsvWriter(outputStream, ',', StandardCharsets.UTF_8);
writer.writeRecord(new String[] {"Index", "Payment Address"});
for(Entry entry : getWalletForm().getNodeEntry(KeyPurpose.RECEIVE).getChildren()) {
NodeEntry childEntry = (NodeEntry)entry;
writer.write(childEntry.getNode().getIndex() + "");
writer.write(childEntry.getAddress().toString());
writer.writeRecord(new String[] {"Index", "Payment Address", "Derivation", "Label"});
for(WalletNode indexNode : purposeNode.getChildren()) {
writer.write(Integer.toString(indexNode.getIndex()));
writer.write(copy.getAddress(indexNode).toString());
writer.write(getDerivationPath(indexNode));
Optional<Entry> optLabelEntry = getWalletForm().getNodeEntry(keyPurpose).getChildren().stream()
.filter(entry -> ((NodeEntry)entry).getNode().getIndex() == indexNode.getIndex()).findFirst();
writer.write(optLabelEntry.isPresent() ? optLabelEntry.get().getLabel() : "");
writer.endRecord();
}
writer.close();

View file

@ -117,20 +117,7 @@ public class ReceiveController extends WalletFormController implements Initializ
}
private void updateDerivationPath(NodeEntry nodeEntry) {
KeyDerivation firstDerivation = getWalletForm().getWallet().getKeystores().get(0).getKeyDerivation();
boolean singleDerivationPath = true;
for(Keystore keystore : getWalletForm().getWallet().getKeystores()) {
if(!keystore.getKeyDerivation().getDerivationPath().equals(firstDerivation.getDerivationPath())) {
singleDerivationPath = false;
break;
}
}
if(singleDerivationPath) {
derivationPath.setText(firstDerivation.extend(nodeEntry.getNode().getDerivation()).getDerivationPath());
} else {
derivationPath.setText(nodeEntry.getNode().getDerivationPath().replace("m", "multi"));
}
derivationPath.setText(getDerivationPath(nodeEntry.getNode()));
}
private void updateLastUsed() {

View file

@ -1,6 +1,9 @@
package com.sparrowwallet.sparrow.wallet;
import com.google.common.eventbus.Subscribe;
import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.WalletNode;
import com.sparrowwallet.sparrow.BaseController;
import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.WalletTabData;
@ -30,4 +33,24 @@ public abstract class WalletFormController extends BaseController {
}
}
}
protected boolean isSingleDerivationPath() {
KeyDerivation firstDerivation = getWalletForm().getWallet().getKeystores().get(0).getKeyDerivation();
for(Keystore keystore : getWalletForm().getWallet().getKeystores()) {
if(!keystore.getKeyDerivation().getDerivationPath().equals(firstDerivation.getDerivationPath())) {
return false;
}
}
return true;
}
protected String getDerivationPath(WalletNode node) {
if(isSingleDerivationPath()) {
KeyDerivation firstDerivation = getWalletForm().getWallet().getKeystores().get(0).getKeyDerivation();
return firstDerivation.extend(node.getDerivation()).getDerivationPath();
}
return node.getDerivationPath().replace("m", "multi");
}
}

View file

@ -171,4 +171,16 @@
.alert .content.label {
-fx-padding: 20px 20px 20px 20px;
}
.icon-button {
-fx-border-style: none;
-fx-border-width: 0;
-fx-border-insets: 0;
-fx-background-color: transparent;
-fx-opacity: 0.7;
}
.icon-button:hover {
-fx-opacity: 1.0;
}

View file

@ -8,6 +8,8 @@
<?import javafx.geometry.Insets?>
<?import com.sparrowwallet.sparrow.control.AddressTreeTable?>
<?import org.controlsfx.glyphfont.Glyph?>
<GridPane hgap="10.0" vgap="10.0" stylesheets="@addresses.css, @wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.AddressesController">
<padding>
<Insets left="25.0" right="25.0" top="15.0" bottom="25.0" />
@ -21,14 +23,17 @@
</rowConstraints>
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
<top>
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
<left>
<Label styleClass="addresses-treetable-label" text="Receiving Addresses"/>
</left>
<right>
<Button fx:id="receiveExportButton" text="Export File..." onAction="#exportReceiveAddresses" />
</right>
</BorderPane>
<HBox alignment="CENTER_LEFT">
<Label styleClass="addresses-treetable-label" text="Receive Addresses"/>
<Button onAction="#exportReceiveAddresses" styleClass="icon-button">
<graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
</graphic>
<tooltip>
<Tooltip text="Export receive addresses as CSV" />
</tooltip>
</Button>
</HBox>
</top>
<center>
<AddressTreeTable fx:id="receiveTable" />
@ -36,7 +41,17 @@
</BorderPane>
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
<top>
<Label styleClass="addresses-treetable-label" text="Change Addresses"/>
<HBox alignment="CENTER_LEFT">
<Label styleClass="addresses-treetable-label" text="Change Addresses"/>
<Button onAction="#exportChangeAddresses" styleClass="icon-button">
<graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
</graphic>
<tooltip>
<Tooltip text="Export change addresses as CSV" />
</tooltip>
</Button>
</HBox>
</top>
<center>
<AddressTreeTable fx:id="changeTable" />

View file

@ -23,15 +23,3 @@
.chart-line-symbol.selected {
-fx-background-color: rgba(30, 136, 207, 0.6);
}
#exportCsv {
-fx-border-style: none;
-fx-border-width: 0;
-fx-border-insets: 0;
-fx-background-color: transparent;
-fx-opacity: 0.7;
}
#exportCsv:hover {
-fx-opacity: 1.0;
}

View file

@ -41,7 +41,7 @@
</Field>
<Field text="Transactions:">
<CopyableLabel fx:id="transactionCount" />
<Button fx:id="exportCsv" maxHeight="25" onAction="#exportCSV" translateY="-1">
<Button fx:id="exportCsv" maxHeight="25" onAction="#exportCSV" translateY="-1" styleClass="icon-button">
<graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
</graphic>