mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
implement changes to export addresses functionality
This commit is contained in:
parent
6785bccf0e
commit
193f88b88f
7 changed files with 84 additions and 46 deletions
|
@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.wallet;
|
||||||
import com.csvreader.CsvWriter;
|
import com.csvreader.CsvWriter;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.sparrowwallet.drongo.KeyPurpose;
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
@ -20,10 +21,12 @@ import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
public class AddressesController extends WalletFormController implements Initializable {
|
public class AddressesController extends WalletFormController implements Initializable {
|
||||||
private static final Logger log = LoggerFactory.getLogger(AddressesController.class);
|
private static final Logger log = LoggerFactory.getLogger(AddressesController.class);
|
||||||
|
public static final int DEFAULT_EXPORT_ADDRESSES_LENGTH = 250;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private AddressTreeTable receiveTable;
|
private AddressTreeTable receiveTable;
|
||||||
|
@ -96,26 +99,36 @@ public class AddressesController extends WalletFormController implements Initial
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exportReceiveAddresses(ActionEvent event) {
|
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();
|
Stage window = new Stage();
|
||||||
|
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
fileChooser.setTitle("Export Addresses File");
|
fileChooser.setTitle("Export Addresses to CSV");
|
||||||
String extension = "txt";
|
fileChooser.setInitialFileName(getWalletForm().getWallet().getName() + "-" + keyPurpose.name().toLowerCase() + "-addresses.txt");
|
||||||
fileChooser.setInitialFileName(getWalletForm().getWallet().getName() + "-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);
|
File file = fileChooser.showSaveDialog(window);
|
||||||
if(file != null) {
|
if(file != null) {
|
||||||
try(FileOutputStream outputStream = new FileOutputStream(file)) {
|
try(FileOutputStream outputStream = new FileOutputStream(file)) {
|
||||||
CsvWriter writer = new CsvWriter(outputStream, ',', StandardCharsets.UTF_8);
|
CsvWriter writer = new CsvWriter(outputStream, ',', StandardCharsets.UTF_8);
|
||||||
writer.writeRecord(new String[] {"Index", "Payment Address"});
|
writer.writeRecord(new String[] {"Index", "Payment Address", "Derivation", "Label"});
|
||||||
for(Entry entry : getWalletForm().getNodeEntry(KeyPurpose.RECEIVE).getChildren()) {
|
for(WalletNode indexNode : purposeNode.getChildren()) {
|
||||||
NodeEntry childEntry = (NodeEntry)entry;
|
writer.write(Integer.toString(indexNode.getIndex()));
|
||||||
writer.write(childEntry.getNode().getIndex() + "");
|
writer.write(copy.getAddress(indexNode).toString());
|
||||||
writer.write(childEntry.getAddress().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.endRecord();
|
||||||
}
|
}
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
|
@ -117,20 +117,7 @@ public class ReceiveController extends WalletFormController implements Initializ
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDerivationPath(NodeEntry nodeEntry) {
|
private void updateDerivationPath(NodeEntry nodeEntry) {
|
||||||
KeyDerivation firstDerivation = getWalletForm().getWallet().getKeystores().get(0).getKeyDerivation();
|
derivationPath.setText(getDerivationPath(nodeEntry.getNode()));
|
||||||
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"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLastUsed() {
|
private void updateLastUsed() {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package com.sparrowwallet.sparrow.wallet;
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
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.BaseController;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.WalletTabData;
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,3 +172,15 @@
|
||||||
.alert .content.label {
|
.alert .content.label {
|
||||||
-fx-padding: 20px 20px 20px 20px;
|
-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;
|
||||||
|
}
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import com.sparrowwallet.sparrow.control.AddressTreeTable?>
|
<?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">
|
<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>
|
<padding>
|
||||||
<Insets left="25.0" right="25.0" top="15.0" bottom="25.0" />
|
<Insets left="25.0" right="25.0" top="15.0" bottom="25.0" />
|
||||||
|
@ -21,14 +23,17 @@
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
<top>
|
<top>
|
||||||
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<HBox alignment="CENTER_LEFT">
|
||||||
<left>
|
<Label styleClass="addresses-treetable-label" text="Receive Addresses"/>
|
||||||
<Label styleClass="addresses-treetable-label" text="Receiving Addresses"/>
|
<Button onAction="#exportReceiveAddresses" styleClass="icon-button">
|
||||||
</left>
|
<graphic>
|
||||||
<right>
|
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
|
||||||
<Button fx:id="receiveExportButton" text="Export File..." onAction="#exportReceiveAddresses" />
|
</graphic>
|
||||||
</right>
|
<tooltip>
|
||||||
</BorderPane>
|
<Tooltip text="Export receive addresses as CSV" />
|
||||||
|
</tooltip>
|
||||||
|
</Button>
|
||||||
|
</HBox>
|
||||||
</top>
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<AddressTreeTable fx:id="receiveTable" />
|
<AddressTreeTable fx:id="receiveTable" />
|
||||||
|
@ -36,7 +41,17 @@
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
|
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
|
||||||
<top>
|
<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>
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<AddressTreeTable fx:id="changeTable" />
|
<AddressTreeTable fx:id="changeTable" />
|
||||||
|
|
|
@ -23,15 +23,3 @@
|
||||||
.chart-line-symbol.selected {
|
.chart-line-symbol.selected {
|
||||||
-fx-background-color: rgba(30, 136, 207, 0.6);
|
-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;
|
|
||||||
}
|
|
|
@ -41,7 +41,7 @@
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Transactions:">
|
<Field text="Transactions:">
|
||||||
<CopyableLabel fx:id="transactionCount" />
|
<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>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
|
||||||
</graphic>
|
</graphic>
|
||||||
|
|
Loading…
Reference in a new issue