add export to specter diy

This commit is contained in:
Craig Raw 2021-05-24 14:20:08 +02:00
parent 9ebbf2557f
commit a60eadf8fc
5 changed files with 59 additions and 7 deletions

View file

@ -43,7 +43,7 @@ public class WalletExportDialog extends Dialog<Wallet> {
if(wallet.getPolicyType() == PolicyType.SINGLE) { if(wallet.getPolicyType() == PolicyType.SINGLE) {
exporters = List.of(new Electrum(), new SpecterDesktop(), new Sparrow()); exporters = List.of(new Electrum(), new SpecterDesktop(), new Sparrow());
} else if(wallet.getPolicyType() == PolicyType.MULTI) { } else if(wallet.getPolicyType() == PolicyType.MULTI) {
exporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new PassportMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new Sparrow()); exporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new PassportMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new SpecterDIY(), new Sparrow());
} else { } else {
throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType()); throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType());
} }

View file

@ -180,7 +180,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle
} }
try { try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
writer.append("# " + getName() + " setup file (created by Sparrow)\n"); writer.append("# " + getName() + " setup file (created by Sparrow)\n");
writer.append("#\n"); writer.append("#\n");
writer.append("Name: ").append(wallet.getName()).append("\n"); writer.append("Name: ").append(wallet.getName()).append("\n");

View file

@ -10,13 +10,10 @@ import com.sparrowwallet.drongo.wallet.WalletModel;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class SpecterDIY implements KeystoreFileImport { public class SpecterDIY implements KeystoreFileImport, WalletExport {
private static final Logger log = LoggerFactory.getLogger(SpecterDIY.class); private static final Logger log = LoggerFactory.getLogger(SpecterDIY.class);
@Override @Override
@ -67,4 +64,36 @@ public class SpecterDIY implements KeystoreFileImport {
public WalletModel getWalletModel() { public WalletModel getWalletModel() {
return WalletModel.SPECTER_DIY; return WalletModel.SPECTER_DIY;
} }
@Override
public void exportWallet(Wallet wallet, OutputStream outputStream) throws ExportException {
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
writer.append("addwallet ").append(wallet.getName()).append("&").append(OutputDescriptor.getOutputDescriptor(wallet).toString().replace('\'', 'h')).append("\n");
writer.flush();
} catch(Exception e) {
log.error("Error exporting Specter DIY wallet", e);
throw new ExportException("Error exporting Specter DIY wallet", e);
}
}
@Override
public String getWalletExportDescription() {
return "Export file or QR that can be read by your Specter DIY using the Wallets > Add Wallet feature.";
}
@Override
public String getExportFileExtension(Wallet wallet) {
return "txt";
}
@Override
public boolean isWalletExportScannable() {
return true;
}
@Override
public boolean walletExportRequiresDecryption() {
return false;
}
} }

View file

@ -1,12 +1,18 @@
package com.sparrowwallet.sparrow.io; package com.sparrowwallet.sparrow.io;
import com.google.common.io.ByteStreams;
import com.sparrowwallet.drongo.ExtendedKey; import com.sparrowwallet.drongo.ExtendedKey;
import com.sparrowwallet.drongo.Network; import com.sparrowwallet.drongo.Network;
import com.sparrowwallet.drongo.OutputDescriptor;
import com.sparrowwallet.drongo.protocol.ScriptType; import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.Wallet;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class SpecterDIYTest extends IoTest { public class SpecterDIYTest extends IoTest {
@Test @Test
public void testImport() throws ImportException { public void testImport() throws ImportException {
@ -21,4 +27,20 @@ public class SpecterDIYTest extends IoTest {
Assert.assertTrue(keystore.isValid()); Assert.assertTrue(keystore.isValid());
Network.set(Network.MAINNET); Network.set(Network.MAINNET);
} }
@Test
public void testExport() throws ExportException, IOException {
OutputDescriptor walletDescriptor = OutputDescriptor.getOutputDescriptor("wsh(sortedmulti(2,[7fd1bbf4/48h/0h/0h/2h]xpub6DnVFCXjZKhSAJw1oGzksdc1CtMxHxqG6DgNSjZHsymMSgcNEb2c3bz5N2bBMEEUFos98CeAWbh1pTMBcJrsKW63icdAQNGT6Aqv1WWrkxg,[8ff26349/48h/0h/0h/2h]xpub6ErPooPdSeBoXVZocBe8EWF9GXjFuV52kme35p4MtrP2SAFdUmgTJM1urrJzSuA44izrEuiQNNdmWEVRaBJcBDcPpnLBR8tP2Pcu2EiyeHu,[ff3305c2/48h/0h/0h/2h]xpub6Dpndp2xurqbfSGhxKVXzk3nJZgah3PdD3qD11KyPicYYBatRxfxqoN7s9tnWKXaz7zhyVqcvnJyak7BVKonW2wTXHd1zNDxJAu8jcxF59j))");
Wallet wallet = walletDescriptor.toWallet();
wallet.setName("Sparrow Multisig");
SpecterDIY specterDIY = new SpecterDIY();
byte[] walletBytes = ByteStreams.toByteArray(getInputStream("specter-diy-export.txt"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
specterDIY.exportWallet(wallet, baos);
String original = new String(walletBytes);
String exported = new String(baos.toByteArray());
Assert.assertEquals(original, exported);
}
} }

View file

@ -0,0 +1 @@
addwallet Sparrow Multisig&wsh(sortedmulti(2,[7fd1bbf4/48h/0h/0h/2h]xpub6DnVFCXjZKhSAJw1oGzksdc1CtMxHxqG6DgNSjZHsymMSgcNEb2c3bz5N2bBMEEUFos98CeAWbh1pTMBcJrsKW63icdAQNGT6Aqv1WWrkxg,[8ff26349/48h/0h/0h/2h]xpub6ErPooPdSeBoXVZocBe8EWF9GXjFuV52kme35p4MtrP2SAFdUmgTJM1urrJzSuA44izrEuiQNNdmWEVRaBJcBDcPpnLBR8tP2Pcu2EiyeHu,[ff3305c2/48h/0h/0h/2h]xpub6Dpndp2xurqbfSGhxKVXzk3nJZgah3PdD3qD11KyPicYYBatRxfxqoN7s9tnWKXaz7zhyVqcvnJyak7BVKonW2wTXHd1zNDxJAu8jcxF59j))