From a121bb5f26a542688565cd8d9b4aa13e4d5cd675 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 28 Jan 2021 10:43:54 +0200 Subject: [PATCH] add passport hww single and multisig importing --- drongo | 2 +- .../sparrowwallet/sparrow/AppController.java | 6 ++- .../sparrow/control/WalletImportDialog.java | 2 +- .../sparrow/io/ColdcardSinglesig.java | 4 +- .../sparrow/io/PassportMultisig.java | 38 ++++++++++++++ .../sparrow/io/PassportSinglesig.java | 48 ++++++++++++++++++ .../keystoreimport/HwAirgappedController.java | 4 +- src/main/resources/image/passport.png | Bin 0 -> 2916 bytes src/main/resources/image/passport@2x.png | Bin 0 -> 4692 bytes src/main/resources/image/passport@3x.png | Bin 0 -> 6079 bytes 10 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/io/PassportMultisig.java create mode 100644 src/main/java/com/sparrowwallet/sparrow/io/PassportSinglesig.java create mode 100644 src/main/resources/image/passport.png create mode 100644 src/main/resources/image/passport@2x.png create mode 100644 src/main/resources/image/passport@3x.png diff --git a/drongo b/drongo index 4b682fb3..a38206f1 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 4b682fb3e710c4b2303295fdfde72195854097dc +Subproject commit a38206f17cd125044d87eb85bf2cf6dcd055e9a0 diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index 4204bbe6..f396efd9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -686,7 +686,11 @@ public class AppController implements Initializable { } private boolean attemptImportWallet(File file, SecureString password) { - List walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new SpecterDesktop(), new CoboVaultSinglesig(), new CoboVaultMultisig()); + List walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), + new Electrum(), + new SpecterDesktop(), + new CoboVaultSinglesig(), new CoboVaultMultisig(), + new PassportSinglesig()); for(WalletImport importer : walletImporters) { try(FileInputStream inputStream = new FileInputStream(file)) { if(importer.isEncrypted(file) && password == null) { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java index 4ea8af2d..596a44f9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -39,7 +39,7 @@ public class WalletImportDialog extends Dialog { AnchorPane.setRightAnchor(scrollPane, 0.0); Accordion importAccordion = new Accordion(); - List keystoreImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig()); + List keystoreImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new PassportSinglesig()); for(KeystoreFileImport importer : keystoreImporters) { FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer); importAccordion.getPanes().add(importPane); diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java index 5ccf25ce..32cf28e1 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java @@ -57,7 +57,7 @@ public class ColdcardSinglesig implements KeystoreFileImport, WalletImport { Map map = gson.fromJson(new InputStreamReader(inputStream, StandardCharsets.UTF_8), stringStringMap); if (map.get("xfp") == null) { - throw new ImportException("File was not a valid Coldcard wallet export"); + throw new ImportException("File was not a valid " + getName() + " wallet export"); } String masterFingerprint = map.get("xfp").getAsString(); @@ -107,7 +107,7 @@ public class ColdcardSinglesig implements KeystoreFileImport, WalletImport { try { wallet.checkWallet(); } catch(InvalidWalletException e) { - throw new ImportException("Imported Coldcard wallet was invalid: " + e.getMessage()); + throw new ImportException("Imported " + getName() + " wallet was invalid: " + e.getMessage()); } return wallet; diff --git a/src/main/java/com/sparrowwallet/sparrow/io/PassportMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/PassportMultisig.java new file mode 100644 index 00000000..0094be72 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/PassportMultisig.java @@ -0,0 +1,38 @@ +package com.sparrowwallet.sparrow.io; + +import com.sparrowwallet.drongo.protocol.ScriptType; +import com.sparrowwallet.drongo.wallet.Keystore; +import com.sparrowwallet.drongo.wallet.WalletModel; + +import java.io.InputStream; + +public class PassportMultisig extends ColdcardMultisig { + @Override + public String getName() { + return "Passport Multisig"; + } + + @Override + public WalletModel getWalletModel() { + return WalletModel.PASSPORT; + } + + @Override + public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException { + Keystore keystore = super.getKeystore(scriptType, inputStream, password); + keystore.setLabel("Passport"); + keystore.setWalletModel(getWalletModel()); + + return keystore; + } + + @Override + public String getKeystoreImportDescription() { + return "Import file or QR created from Settings > Pair Software Wallet > Sparrow > Multisig > microSD/QR on your Passport."; + } + + @Override + public boolean isKeystoreImportScannable() { + return true; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/io/PassportSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/PassportSinglesig.java new file mode 100644 index 00000000..4191f015 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/PassportSinglesig.java @@ -0,0 +1,48 @@ +package com.sparrowwallet.sparrow.io; + +import com.sparrowwallet.drongo.protocol.ScriptType; +import com.sparrowwallet.drongo.wallet.Keystore; +import com.sparrowwallet.drongo.wallet.WalletModel; + +import java.io.InputStream; + +public class PassportSinglesig extends ColdcardSinglesig { + @Override + public String getName() { + return "Passport"; + } + + @Override + public String getKeystoreImportDescription() { + return "Import file or QR created from Settings > Pair Software Wallet > Sparrow > Single Sig > microSD/QR on your Passport."; + } + + @Override + public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException { + Keystore keystore = super.getKeystore(scriptType, inputStream, password); + keystore.setLabel("Passport"); + keystore.setWalletModel(getWalletModel()); + + return keystore; + } + + @Override + public WalletModel getWalletModel() { + return WalletModel.PASSPORT; + } + + @Override + public boolean isWalletImportScannable() { + return true; + } + + @Override + public boolean isKeystoreImportScannable() { + return true; + } + + @Override + public String getWalletImportDescription() { + return getKeystoreImportDescription(); + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java index 11621179..37e68084 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java @@ -16,9 +16,9 @@ public class HwAirgappedController extends KeystoreImportDetailController { public void initializeView() { List importers = Collections.emptyList(); if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) { - importers = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new SpecterDIY()); + importers = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new PassportSinglesig(), new SpecterDIY()); } else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) { - importers = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new SpecterDIY()); + importers = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new PassportMultisig(), new SpecterDIY()); } for(KeystoreImport importer : importers) { diff --git a/src/main/resources/image/passport.png b/src/main/resources/image/passport.png new file mode 100644 index 0000000000000000000000000000000000000000..ce3b73cc8772dcc0de5402b16b62621e6c26eb9a GIT binary patch literal 2916 zcmZ`*4Lp-;8-K>s%xC#%3e87y)b?z{Fxz~N#2g`^I<@g&*_Ul>dP`ptS)5dFACgLR z`kHJC#L;5#r29wG!uWgEhF>JAQooX{SCXXUj79&pt0Ifx^J zxIC6bAi~%kPuj}hX-R>f;7L=s zBti@TS_aC201h3-007dO6B;fFX9iHB1Ux(|TEK?zGM-SW0;nK-XX9i)t1R@CQhA8TxVV4>5=bK9U0f|Z$S*dM!F+`3Vzq|U17wJgi{>TgE+(czd(w#^Xf~nwi!OtQN+<+{V0M19Xz*KBHe=`1ZK1V|T zy2Lbix+-GQKbh84a6&)@mFH;6xf(yTDil7obTs@%zkUJe=tqz5SOLHcEkAFM&^V2O za9-TX<(Q^xSN@43=Vp`r148yZ%CbAPe6jY5Wv|GEt;dt1+>lO;6DX1`!_*6{7|7Q4 zfJmD@u6eVgOV21TJ)gmdy}9b)#dfq;n88~MdyYuFv2(cd)*X&W(0t;Io2X0J^yx_N z#=D;q?ml!p*imSIl|R3M^10@sI+B|e4l~o%`Y0AX4*BJ z96_X)k%q8~aen5qF(^&zXcb|Uq7WQFDTV4no^huwF{FLmtxMEGa#ZiKKd^R_k| zQxf?y-6&1Rq}{Xq-d_5!l+(wQu6&6yv1rTHX=l$We$CEFNMrh&5k;Q*k>%x1&TYZI z-#7MS$|EZ=40H4IYzOHSvZoet`Wu4)T)J%;E7+&GET zlkEytG*oHMfYF)eF@_x`hv=EQX)6-^Q+4h4=*)ccS5xc)`Hc7a1!Z;-#AVA&U`+<0#W0yyQRV6*1-+*n$v1+ zuJeyIu+7)c*5_xL2=)x19yg-SYcXA&inq~QDxHwU=bK{(gV8meZR?7u24(GB)6(Ry z>LRP~ba3s3JVtSb1$5{MqxH_;7cc&@#^g-f?Cc|r=X+OC@=})P1-xz{<)p+ndGrN_ zx%)3N=pVX>DWLCKgeg47V;L|R(yKE=PPLrtNIsK7*2iXFzO7k|h*TI=*F9)P>*4Zf zCxbZgVg8rosn6=Er5C&yL^H-uim(E|4aNn9?bV(kw?;CG0&F)xfro#NIvDUGWP3>x zwnWXL1UP*u+^vY6(A~3QP^za^a60(o;v*j#58Plc8~S@;VRNm}dDWaypQ;C0wZ^_! zeN58uJDm|9%UStJr^~HOmL;3pum%WIWe!K{nf75q30C}MUUR0KaSu3O|*6B znXqMkhIUxrUdS%Vv~GAr7y0qir&hPO^r!kfa(|3>C84C6>F`$g``VU}u)ZW|Qx|`I zMJUO&`Q>#m`ao;tTWhjh({HxTWByq7sg{1XzNhhIEd%qr1DnvEthtZC20~^}`2+lZ zFyls*Q$9FS^q^r8jrN81$e?q-bwc*7)*h>CsfD%9dDYU-qp!~yWL%#czAE-)d|L07 z?&I~V5&VO)Cr?Tu&OQ7RLOOVRhi8@E^EK}s@K3wVvls4Jx?sPl?n8V0iuchg_Pg^GGi`cRC;={u_%zrP5K8}%q;F=W8%OiJ(sQK1((=xx=gW)R|b%7M$!4VPSX+y$| z?uu5ooxIY+X1Pq^T7ydAyZ$=Ej+>uH-^DG>f!ySC8+%TumsVJ#Zs;BD?u~zFT>Wcu zob?>qynrGFioA)izl`bePMdtT7o|>xQi2U}H#fg)$P!X*s%%k($SvNxYY@LJG^~tA zZvEGgL;9@zUYrAcb8a2NInSnZ{j*X0z7O`lCIgqQ-W44-$)3|NPghTl5I^99F+-fL zg~snwu?NmBta;$bGK~HQbEalCA?qT($udn{uD_gqeT+(UwY>c{&XScm^r3DZYRKjJC4X170aQy??I!ocYq&XR SQI7J@q8}sByTo(t*8c)%hD@~p literal 0 HcmV?d00001 diff --git a/src/main/resources/image/passport@2x.png b/src/main/resources/image/passport@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bde7bb7d3f09e3f181ab9211cf6d7b0f5cf8c263 GIT binary patch literal 4692 zcmZ`-2|U!>7awDrtV4Dt%e?Gn#*$@>vG2x2^oV4b!6ath82eI0Dnzy{5h2B zEFohl4_PX*m#9XC{zJW&*T46h&;8wV&-s4Ox%b?2f1lrP&K&ZDwj&EL~5~JHg zwr~yr066zVfooz58P z$@oyIWF#CO92^V_R)>)&-f&eN9UVAA4X&o9!a%45g!)r)Au9d>&~Hxu_G3Z_@T3sQ zR3gb=YTGZ)gA_>BlabjD^w0Heo_NoH;*bL=Cw8LXJ>i5C1V4g5H2|&(Q-%ME$5`z@ zME`*A*C7`#9N(G^+qNeTecTu6>KVg1kcZY3E zA#9hW1BrA3{d1Lmb&_h7qJyU^QdM;ep-$P_}r&g>X-`#;^!cqe;80O>^Fc2T0W)V>pTD}N?n zDMUsI;&up(`RoMPt@|1O!@r|Hk&6C1#82v-O)16 zEt-R|r++^K&>ZVYs2%`->yxF4p+gAM@=;E*tD|TW{mnRLAolP+{?X#`-Ue1H7b9;g z1^#`4HSUrYwR5M0s^kwv1he?+Qm+|6GM=1z+HynCJkF3a!%o5%BKdSd8#u^sZDbKt zM{K8A`T4o!jyFVo9lzW=(h&Z3ykopKDf~@OZ|G*_+UBhO>>C}ehSc9+(WeXyq@=)L z5Qv2Z2xR)#FcexK|5%IsHU=Bq({Hz7f1HH0)W3i6g9q=Y}l@$q*E}$6W?Zd zr}g|3Kfm*1T-8(@|VoqO6_rdlntY z7V0VMe=_?hM<;UgbSjjA>U2%asI<qMX#cwp5wm-Fogy$F zL$&dm5`XH1Ul=%4KO&t0ND*4)V6%>X;_iWt?y0>sb$6(j=RPOT{U*>UN5eOVJ2A+5 z5OP&${&0NH!=Y8drr&u?<6- z3DZJe(>DBf@_nYTdUW_K@PDChoIac?Y zYM-8{96zg(*jjWU^?e0-zpzJ9fYRl#`m(Zxx2>(MavZ`$l|l!;YA&yci0A1sJaIm4 z-nt9rbGJsdJLfw85V5@>E-qelY3Y1a#zSeeM8?1u$ET)mF?@o}(e%*9iJRw3jf9U< zJ zjre=juSTvSSqe~~gjpS2V6=e{9$1pgCWLt~EBqTR=6)8>eTgth_j=AG9$C4ubT?+j zfm*N~<>W=Y@G^>}r4YqZ1ea>%3}n+XT5FHSYfHy-ow|$>6cj8E758j$N(Z$VMR8Im zaD~BE8kk&7jGA+Tmq$u}L&r1H%bEUe5AADgK{Wl5IV{xw>;)8Am4LH5Lp@3$%y1XS zhH7fR0VkGXAMP1W(My}>io&ad*V^Q}+Pe+&x3Kv_Az{KJx4Vh)J#mC%K|M%1XPD&G zXX5XP?ga0v*D29yq7an9M(OLtfZjFAJyf~0WVd6cU}F(a^j^jC^o;r>W*DZ{ z(M9ZbU|e6lPTgU12=M9W_CgHxFLX9Qx!d+?9=c$}&)#cL%SG({qYmA^EXlh4T0<(O zknyOF_}izQZ0HXyj;th}x(GdEu%^oyUP=_9rvW@fr`xoT$R=NY$Nn7Z>T*QrPq?u# z=E}5d`^~`?v($Gm^i+Rlz1yYvJ{patKwFBv73VYShnt?JZQhcy|JRe_`-21_$XB&F zbh+>l@6_o5?o#;Z#mjbb4+4BooK|TsOC%_XCbrlJ_4%5$;t@w^{lCXvPJHCy(wCKKaFu5&bSltp2% z(4BW+i%@1Z`hrJZ$Jwh|>A?1);JZLuR$Ser;1TZKT_h0Z>Xy@>*RFLu1vPv#&?w*~ux1=c&43 zD+kdr8=;9$lzU~3j^JqiAo+QtC#T&tCMr}8H5|>mod+MA$=-YRLdnds*`|#IeJdP~ zpGF)b^^BQ;P}W#bZMIpSU6$iW56uR3xaLz0;Uz9Gy&82V4(|O}eP1TOd32hadf1(?y`rt;PO6Dz zu~#E37wb3;?uI%Zn*VCfU0Yi_(A;cbm0SwD#JNFT@OhKu8oTGnuPR~+4E)S){NMpm zb)w==!7Gm)pRcbd@S4jEsBdl_EeX+EUS2+q#Y#4L8MP;CD)P}b6-6S}=qT>)zPvHY zULP1w+{DJ7r>wxHl!kcVJm}%q;yxUZ_@JI_$`6yUJz*HLT%G&{e$#h>8~1kbUONL8pN*yj@{4KVf$K!-Ryi;e}eLSH$_57mO`56Sly z>+|z3AUq2+#2nuZ8n2F%ABNF-=wY?p?(4%Xbr5LE)+@~!ppRWA#4}?~-cLNy!&_r8 z|1bGOE_di!Tzh->ta}1Zpc+cM^f5;LeOHR^+`G<2+^k>!k)mEd(I9i75s@JV1P#4;1g z+02Wo5$})x1cm;ABw*Zf%)3O1B=E{gFx?Kiog8;gVuf8Hz~dvV`S;HBlBuEdW_ z_^%=yjkU>T;Oe4I{Rg43ia0`tvUu4Z(R&E-%|sLX-1D5p&LK zg9c8`=W!qlUD83v(7gs+txqli#3GMb<_ubF(P+v?_f5}b;RlF^XV)IR=vn_nyA2iL z+KQixX{p;fgNJ{vQ3Qh=)Z9#<+)+7VCwan~BtbnzBYT(;e=WvWq#jnS?V z^GO>JlaE1j#}?>)4LNn)=OQ$6RtUePis=Y_RZNy2-WT_#smOBgxz8cuW^JM< zE&TIkmi4BIi3z5aaW=GsXn2)u8wLW@31hDcGN^dZy0W~yv}6g3`Ue|hk1dOY9t&tiKz;H}0TY=6~C+IcSBiGd!~5m_2}w@TerRE@m(NjVBTCrImaNB~BiX{F-!>G45Lx=V7r72DPEg6xoX9G$o?dZL z0ClY!D8JU5qSr~VOwp&JWF*jGqZSEj@4G*baOIE2l!>(pKl72EYjw>HD`dtWBcS$u zfw8rbs)8f{Z|#(^*a9?BSEaZh60C{tE#|XHm}FVD3M;e8$dTt`1FK%Jl;yCYS6|aV zw^}a8c&oy3Y-%h#OH5LTkLG0~Z4A>Q1$^PAvM2kMU&N^h96l0Qdp;htT++G7EAi^F z-pMmp^_ZE<&9Jhp7cVU?di%$wCST>Bg|1psEA%AZJhzNVi+z<{HyQOxTh<8m*$QEs zb0+^5C!21t=zQtYyV8?Py=%9)7Z0%ueGP9J>|JnLSeuV0G#DnEV`nK)Lbkd@wv?-afsa8NjiaWS>`>y*@TMsegt&uCY`{!!9>xP=f>>r1@XL z>Sm0}Sau`_f0f}Eb%`m}<|=t+)OSfy@!HeKNXXmOnw;WTyDgzi1LXU(6(@-sr72p9 osjFOAxz(S(C%z947K1i;8E;eEkwfE2+kcK&n%bIF7`ey%4?HQf)c^nh literal 0 HcmV?d00001 diff --git a/src/main/resources/image/passport@3x.png b/src/main/resources/image/passport@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..c5dfbd3582c55eda670f2abf58832b56686ccd2c GIT binary patch literal 6079 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 WA&{Ne6LI-559n$cB8VFH5&sAFqcYt9 literal 0 HcmV?d00001