support account renaming, configuration of mix index range

This commit is contained in:
Craig Raw 2021-10-27 16:14:35 +02:00
parent 9520f6d218
commit 37aa3c9712
18 changed files with 228 additions and 51 deletions

2
drongo

@ -1 +1 @@
Subproject commit 24d9e5fcda84058c48964e2abe21600f61ec359d Subproject commit 434c18ef0a97d899b534bf81496207542ebbd395

View file

@ -44,6 +44,7 @@ import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.geometry.Side; import javafx.geometry.Side;
import javafx.scene.Node; import javafx.scene.Node;
@ -1282,7 +1283,7 @@ public class AppController implements Initializable {
addWalletSubTab(subTabs, storage, wallet, backupWallet); addWalletSubTab(subTabs, storage, wallet, backupWallet);
Tab masterTab = subTabs.getTabs().stream().filter(tab -> ((WalletTabData)tab.getUserData()).getWallet().isMasterWallet()).findFirst().orElse(subTabs.getTabs().get(0)); Tab masterTab = subTabs.getTabs().stream().filter(tab -> ((WalletTabData)tab.getUserData()).getWallet().isMasterWallet()).findFirst().orElse(subTabs.getTabs().get(0));
Label masterLabel = (Label)masterTab.getGraphic(); Label masterLabel = (Label)masterTab.getGraphic();
masterLabel.setText(getAutomaticName(wallet.getMasterWallet())); masterLabel.setText(wallet.getMasterWallet().getLabel() != null ? wallet.getMasterWallet().getLabel() : getAutomaticName(wallet.getMasterWallet()));
Platform.runLater(() -> { Platform.runLater(() -> {
setSubTabsVisible(subTabs, true); setSubTabsVisible(subTabs, true);
}); });
@ -1312,7 +1313,9 @@ public class AppController implements Initializable {
try { try {
Tab subTab = new Tab(); Tab subTab = new Tab();
subTab.setClosable(false); subTab.setClosable(false);
Label subTabLabel = new Label(wallet.isMasterWallet() ? getAutomaticName(wallet) : wallet.getName()); String label = wallet.getLabel() != null ? wallet.getLabel() : (wallet.isMasterWallet() ? getAutomaticName(wallet) : wallet.getName());
Label subTabLabel = new Label(label);
subTabLabel.setPadding(new Insets(0, 3, 0, 3));
subTabLabel.setGraphic(getSubTabGlyph(wallet)); subTabLabel.setGraphic(getSubTabGlyph(wallet));
subTabLabel.setContentDisplay(ContentDisplay.TOP); subTabLabel.setContentDisplay(ContentDisplay.TOP);
subTabLabel.setAlignment(Pos.TOP_CENTER); subTabLabel.setAlignment(Pos.TOP_CENTER);
@ -1330,6 +1333,9 @@ public class AppController implements Initializable {
TabData tabData = new WalletTabData(TabData.TabType.WALLET, walletForm); TabData tabData = new WalletTabData(TabData.TabType.WALLET, walletForm);
subTab.setUserData(tabData); subTab.setUserData(tabData);
if(!wallet.isWhirlpoolChildWallet()) {
subTab.setContextMenu(getSubTabContextMenu(subTab));
}
subTabs.getTabs().add(subTab); subTabs.getTabs().add(subTab);
subTabs.getTabs().sort((o1, o2) -> { subTabs.getTabs().sort((o1, o2) -> {
@ -1380,24 +1386,6 @@ public class AppController implements Initializable {
return null; return null;
} }
public void openExamples(ActionEvent event) {
try {
addTransactionTab("p2pkh", null, "01000000019c2e0f24a03e72002a96acedb12a632e72b6b74c05dc3ceab1fe78237f886c48010000006a47304402203da9d487be5302a6d69e02a861acff1da472885e43d7528ed9b1b537a8e2cac9022002d1bca03a1e9715a99971bafe3b1852b7a4f0168281cbd27a220380a01b3307012102c9950c622494c2e9ff5a003e33b690fe4832477d32c2d256c67eab8bf613b34effffffff02b6f50500000000001976a914bdf63990d6dc33d705b756e13dd135466c06b3b588ac845e0201000000001976a9145fb0e9755a3424efd2ba0587d20b1e98ee29814a88ac06241559");
addTransactionTab("p2sh", null, "0100000003a5ee1a0fd80dfbc3142df136ab56e082b799c13aa977c048bdf8f61bd158652c000000006b48304502203b0160de302cded63589a88214fe499a25aa1d86a2ea09129945cd632476a12c022100c77727daf0718307e184d55df620510cf96d4b5814ae3258519c0482c1ca82fa0121024f4102c1f1cf662bf99f2b034eb03edd4e6c96793cb9445ff519aab580649120ffffffff0fce901eb7b7551ba5f414735ff93b83a2a57403df11059ec88245fba2aaf1a0000000006a47304402204089adb8a1de1a9e22aa43b94d54f1e54dc9bea745d57df1a633e03dd9ede3c2022037d1e53e911ed7212186028f2e085f70524930e22eb6184af090ba4ab779a5b90121030644cb394bf381dbec91680bdf1be1986ad93cfb35603697353199fb285a119effffffff0fce901eb7b7551ba5f414735ff93b83a2a57403df11059ec88245fba2aaf1a0010000009300493046022100a07b2821f96658c938fa9c68950af0e69f3b2ce5f8258b3a6ad254d4bc73e11e022100e82fab8df3f7e7a28e91b3609f91e8ebf663af3a4dc2fd2abd954301a5da67e701475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052aeffffffff02a3b81b00000000001976a914ea00917f128f569cbdf79da5efcd9001671ab52c88ac80969800000000001976a9143dec0ead289be1afa8da127a7dbdd425a05e25f688ac00000000");
addTransactionTab("p2sh-p2wpkh", null, "01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000");
addTransactionTab("p2sh-p2wsh", null, "01000000000101708256c5896fb3f00ef37601f8e30c5b460dbcd1fca1cd7199f9b56fc4ecd5400000000023220020615ae01ed1bc1ffaad54da31d7805d0bb55b52dfd3941114330368c1bbf69b4cffffffff01603edb0300000000160014bbef244bcad13cffb68b5cef3017c7423675552204004730440220010d2854b86b90b7c33661ca25f9d9f15c24b88c5c4992630f77ff004b998fb802204106fc3ec8481fa98e07b7e78809ac91b6ccaf60bf4d3f729c5a75899bb664a501473044022046d66321c6766abcb1366a793f9bfd0e11e0b080354f18188588961ea76c5ad002207262381a0661d66f5c39825202524c45f29d500c6476176cd910b1691176858701695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000");
addTransactionTab("p2wpkh", null, "01000000000101109d2e41430bfdec7e6dfb02bf78b5827eeb717ef25210ff3203b0db8c76c9260000000000ffffffff01a032eb0500000000160014bbef244bcad13cffb68b5cef3017c742367555220247304402202f7cac3494e521018ae0be4ca18517639ef7c00658d42a9f938b2b344c8454e2022039a54218832fad5d14b331329d9042c51ee6be287e95e49ee5b96fda1f5ce13f0121026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf300000000");
addTransactionTab("p2wsh", null, "0100000000010193a2db37b841b2a46f4e9bb63fe9c1012da3ab7fe30b9f9c974242778b5af8980000000000ffffffff01806fb307000000001976a914bbef244bcad13cffb68b5cef3017c7423675552288ac040047304402203cdcaf02a44e37e409646e8a506724e9e1394b890cb52429ea65bac4cc2403f1022024b934297bcd0c21f22cee0e48751c8b184cc3a0d704cae2684e14858550af7d01483045022100feb4e1530c13e72226dc912dcd257df90d81ae22dbddb5a3c2f6d86f81d47c8e022069889ddb76388fa7948aaa018b2480ac36132009bb9cfade82b651e88b4b137a01695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000");
//addTransactionTab("test1", null, "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd0481500400002305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900");
//addTransactionTab("3of3-1s.psbt", null, "70736274ff0100550200000001294c4871c059bb76be81e94b78059ee2e0c9b1b47f38edb6b4e75916062394930000000000feffffff01f82a0000000000001976a914e65b294f890792f2c2725d488567018d660f0cf488ac701c09004f0102aa7ed3044b1635bb800000021bf4bfc48934b7966b39bdebb689525d9b8bfed5c8b16e8c58f9afe4641d6d5f03800b5dbec0355c9f0b5e8227bc903e9d0ff1fe6ced0dcfb6d416541c7412c4331406b57041300000800000008000000080020000804f0102aa7ed3042cd31dee80000002d544b2364010378f8c6cec85f6b7ed83a8203dcdbedb97e2625f431f897b837e0363428de8fcfbfe373c0d9e1e0cc8163d886764bafe71c5822eaa232981356589145f63394f300000800000008000000080020000804f0102aa7ed3049ec7d9f580000002793e04aff18b4e40ebc48bcdc6232c54c69cf7265a38fbd85b35705e34d2d42f03368e79aa2b2b7f736d156905a7a45891df07baa2d0b7f127a537908cb82deed514130a48af300000800000008000000080020000800001012b983a000000000000220020f64748dad1cbad107761aaed5c59f25aba006498d260b440e0a091691350c9aa010569532102f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3262103171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a221037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f753ae220602f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3261c130a48af300000800000008000000080020000800000000000000000220603171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a21c5f63394f300000800000008000000080020000800000000000000000220203171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a24830450221008d27cc4b03bc543726e73b69e7980e7364d6f33f979a5cd9b92fb3d050666bd002204fc81fc9c67baf7c3b77041ed316714a9c117a5bdbb020e8c771ea3bdc342434012206037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f71c06b570413000008000000080000000800200008000000000000000000000");
//addTransactionTab("signer.psbt", null, "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000");
//addTransactionTab("combiner.psbt", null, "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000");
addTransactionTab("finalizer.psbt", null, "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000");
} catch(Exception e) {
log.error("Error opening examples", e);
}
}
private void addTransactionTab(String name, File file, String string) throws ParseException, PSBTParseException, TransactionParseException { private void addTransactionTab(String name, File file, String string) throws ParseException, PSBTParseException, TransactionParseException {
if(Utils.isBase64(string) && !Utils.isHex(string)) { if(Utils.isBase64(string) && !Utils.isHex(string)) {
addTransactionTab(name, file, Base64.getDecoder().decode(string)); addTransactionTab(name, file, Base64.getDecoder().decode(string));
@ -1579,6 +1567,28 @@ public class AppController implements Initializable {
return contextMenu; return contextMenu;
} }
private ContextMenu getSubTabContextMenu(Tab subTab) {
ContextMenu contextMenu = new ContextMenu();
MenuItem rename = new MenuItem("Rename Account");
rename.setOnAction(event -> {
Label subTabLabel = (Label)subTab.getGraphic();
WalletLabelDialog walletLabelDialog = new WalletLabelDialog(subTabLabel.getText());
Optional<String> optLabel = walletLabelDialog.showAndWait();
if(optLabel.isPresent()) {
String label = optLabel.get();
subTabLabel.setText(label);
WalletTabData walletTabData = (WalletTabData)subTab.getUserData();
Wallet wallet = walletTabData.getWallet();
wallet.setLabel(label);
EventManager.get().post(new WalletLabelChangedEvent(wallet));
}
});
contextMenu.getItems().add(rename);
return contextMenu;
}
public void setServerType(ServerType serverType) { public void setServerType(ServerType serverType) {
if(serverType == ServerType.PUBLIC_ELECTRUM_SERVER && !serverToggle.getStyleClass().contains("public-server")) { if(serverType == ServerType.PUBLIC_ELECTRUM_SERVER && !serverToggle.getStyleClass().contains("public-server")) {
serverToggle.getStyleClass().add("public-server"); serverToggle.getStyleClass().add("public-server");

View file

@ -83,8 +83,13 @@ public class MixStatusCell extends TreeTableCell<Entry, UtxoEntry.MixStatus> {
"\nTo prevent sleeping, use the " + getPlatformSleepConfig() + " or enable the function in the Tools menu."); "\nTo prevent sleeping, use the " + getPlatformSleepConfig() + " or enable the function in the Tools menu.");
setTooltip(tt); setTooltip(tt);
double fromValue = 1.0;
if(mixErrorTimestamp != null) {
fromValue -= (double)(System.currentTimeMillis() - mixErrorTimestamp) / (ERROR_DISPLAY_MINUTES * 60 * 1000);
}
FadeTransition ft = new FadeTransition(Duration.minutes(ERROR_DISPLAY_MINUTES), failGlyph); FadeTransition ft = new FadeTransition(Duration.minutes(ERROR_DISPLAY_MINUTES), failGlyph);
ft.setFromValue(1); ft.setFromValue(Math.max(0, fromValue));
ft.setToValue(0); ft.setToValue(0);
ft.setOnFinished(event -> { ft.setOnFinished(event -> {
setTooltip(null); setTooltip(null);

View file

@ -0,0 +1,65 @@
package com.sparrowwallet.sparrow.control;
import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import org.controlsfx.control.textfield.CustomTextField;
import org.controlsfx.control.textfield.TextFields;
import org.controlsfx.glyphfont.Glyph;
import org.controlsfx.validation.ValidationSupport;
import org.controlsfx.validation.Validator;
import org.controlsfx.validation.decoration.StyleClassValidationDecoration;
public class WalletLabelDialog extends Dialog<String> {
private final CustomTextField label;
public WalletLabelDialog(String initialName) {
final DialogPane dialogPane = getDialogPane();
AppServices.setStageIcon(dialogPane.getScene().getWindow());
setTitle("Account Name");
dialogPane.setHeaderText("Enter a name for this account:");
dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
dialogPane.getButtonTypes().addAll(ButtonType.CANCEL);
dialogPane.setPrefWidth(400);
dialogPane.setPrefHeight(200);
AppServices.moveToActiveWindowScreen(this);
Glyph wallet = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.WALLET);
wallet.setFontSize(50);
dialogPane.setGraphic(wallet);
final VBox content = new VBox(20);
label = (CustomTextField) TextFields.createClearableTextField();
label.setText(initialName);
label.setTextFormatter(new TextFormatter<>((change) -> {
change.setText(change.getText().replaceAll("[\\\\/:*?\"<>|]", "_"));
return change;
}));
content.getChildren().add(label);
dialogPane.setContent(content);
ValidationSupport validationSupport = new ValidationSupport();
Platform.runLater(() -> {
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
validationSupport.registerValidator(label, Validator.combine(
Validator.createEmptyValidator("Account name is required")
));
});
final ButtonType okButtonType = new javafx.scene.control.ButtonType("Rename Account", ButtonBar.ButtonData.OK_DONE);
dialogPane.getButtonTypes().addAll(okButtonType);
Button okButton = (Button)dialogPane.lookupButton(okButtonType);
BooleanBinding isInvalid = Bindings.createBooleanBinding(() -> label.getText().length() == 0, label.textProperty());
okButton.disableProperty().bind(isInvalid);
label.setPromptText("Account Name");
Platform.runLater(label::requestFocus);
setResultConverter(dialogButton -> dialogButton == okButtonType ? label.getText() : null);
}
}

View file

@ -0,0 +1,13 @@
package com.sparrowwallet.sparrow.event;
import com.sparrowwallet.drongo.wallet.Wallet;
public class WalletLabelChangedEvent extends WalletChangedEvent {
public WalletLabelChangedEvent(Wallet wallet) {
super(wallet);
}
public String getLabel() {
return getWallet().getLabel();
}
}

View file

@ -44,7 +44,6 @@ public class Config {
private boolean showLoadingLog = true; private boolean showLoadingLog = true;
private boolean showUtxosChart = true; private boolean showUtxosChart = true;
private boolean preventSleep = false; private boolean preventSleep = false;
private IndexRange postmixIndexRange = IndexRange.FULL;
private List<File> recentWalletFiles; private List<File> recentWalletFiles;
private Integer keyDerivationPeriod; private Integer keyDerivationPeriod;
private File hwi; private File hwi;
@ -56,8 +55,6 @@ public class Config {
private CoreAuthType coreAuthType; private CoreAuthType coreAuthType;
private File coreDataDir; private File coreDataDir;
private String coreAuth; private String coreAuth;
private Boolean coreMultiWallet;
private String coreWallet;
private String electrumServer; private String electrumServer;
private File electrumServerCert; private File electrumServerCert;
private boolean useProxy; private boolean useProxy;
@ -290,15 +287,6 @@ public class Config {
this.preventSleep = preventSleep; this.preventSleep = preventSleep;
} }
public IndexRange getPostmixIndexRange() {
return postmixIndexRange;
}
public void setPostmixIndexRange(IndexRange postmixIndexRange) {
this.postmixIndexRange = postmixIndexRange;
flush();
}
public List<File> getRecentWalletFiles() { public List<File> getRecentWalletFiles() {
return recentWalletFiles; return recentWalletFiles;
} }

View file

@ -236,6 +236,10 @@ public class DbPersistence implements Persistence {
} }
} }
if(dirtyPersistables.label != null) {
walletDao.updateLabel(wallet.getId(), dirtyPersistables.label.length() > 255 ? dirtyPersistables.label.substring(0, 255) : dirtyPersistables.label);
}
if(dirtyPersistables.blockHeight != null) { if(dirtyPersistables.blockHeight != null) {
walletDao.updateStoredBlockHeight(wallet.getId(), dirtyPersistables.blockHeight); walletDao.updateStoredBlockHeight(wallet.getId(), dirtyPersistables.blockHeight);
} }
@ -641,6 +645,13 @@ public class DbPersistence implements Persistence {
} }
} }
@Subscribe
public void walletLabelChanged(WalletLabelChangedEvent event) {
if(persistsFor(event.getWallet())) {
dirtyPersistablesMap.computeIfAbsent(event.getWallet(), key -> new DirtyPersistables()).label = event.getLabel();
}
}
@Subscribe @Subscribe
public void walletBlockHeightChanged(WalletBlockHeightChangedEvent event) { public void walletBlockHeightChanged(WalletBlockHeightChangedEvent event) {
if(persistsFor(event.getWallet())) { if(persistsFor(event.getWallet())) {
@ -701,6 +712,7 @@ public class DbPersistence implements Persistence {
private static class DirtyPersistables { private static class DirtyPersistables {
public boolean clearHistory; public boolean clearHistory;
public final List<WalletNode> historyNodes = new ArrayList<>(); public final List<WalletNode> historyNodes = new ArrayList<>();
public String label;
public Integer blockHeight = null; public Integer blockHeight = null;
public Integer gapLimit = null; public Integer gapLimit = null;
public final List<Entry> labelEntries = new ArrayList<>(); public final List<Entry> labelEntries = new ArrayList<>();
@ -715,6 +727,7 @@ public class DbPersistence implements Persistence {
return "Dirty Persistables" + return "Dirty Persistables" +
"\nClear history:" + clearHistory + "\nClear history:" + clearHistory +
"\nNodes:" + historyNodes + "\nNodes:" + historyNodes +
"\nLabel:" + label +
"\nBlockHeight:" + blockHeight + "\nBlockHeight:" + blockHeight +
"\nGap limit:" + gapLimit + "\nGap limit:" + gapLimit +
"\nTx labels:" + labelEntries.stream().filter(entry -> entry instanceof TransactionEntry).map(entry -> ((TransactionEntry)entry).getBlockTransaction().getHash().toString()).collect(Collectors.toList()) + "\nTx labels:" + labelEntries.stream().filter(entry -> entry instanceof TransactionEntry).map(entry -> ((TransactionEntry)entry).getBlockTransaction().getHash().toString()).collect(Collectors.toList()) +

View file

@ -8,16 +8,16 @@ import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate; import org.jdbi.v3.sqlobject.statement.SqlUpdate;
public interface MixConfigDao { public interface MixConfigDao {
@SqlQuery("select id, scode, mixOnStartup, mixToWalletFile, mixToWalletName, minMixes, receiveIndex, changeIndex from mixConfig where wallet = ?") @SqlQuery("select id, scode, mixOnStartup, indexRange, mixToWalletFile, mixToWalletName, minMixes, receiveIndex, changeIndex from mixConfig where wallet = ?")
@RegisterRowMapper(MixConfigMapper.class) @RegisterRowMapper(MixConfigMapper.class)
MixConfig getForWalletId(Long id); MixConfig getForWalletId(Long id);
@SqlUpdate("insert into mixConfig (scode, mixOnStartup, mixToWalletFile, mixToWalletName, minMixes, receiveIndex, changeIndex, wallet) values (?, ?, ?, ?, ?, ?, ?, ?)") @SqlUpdate("insert into mixConfig (scode, mixOnStartup, indexRange, mixToWalletFile, mixToWalletName, minMixes, receiveIndex, changeIndex, wallet) values (?, ?, ?, ?, ?, ?, ?, ?, ?)")
@GetGeneratedKeys("id") @GetGeneratedKeys("id")
long insertMixConfig(String scode, Boolean mixOnStartup, String mixToWalletFile, String mixToWalletName, Integer minMixes, int receiveIndex, int changeIndex, long wallet); long insertMixConfig(String scode, Boolean mixOnStartup, String indexRange, String mixToWalletFile, String mixToWalletName, Integer minMixes, int receiveIndex, int changeIndex, long wallet);
@SqlUpdate("update mixConfig set scode = ?, mixOnStartup = ?, mixToWalletFile = ?, mixToWalletName = ?, minMixes = ?, receiveIndex = ?, changeIndex = ?, wallet = ? where id = ?") @SqlUpdate("update mixConfig set scode = ?, mixOnStartup = ?, indexRange = ?, mixToWalletFile = ?, mixToWalletName = ?, minMixes = ?, receiveIndex = ?, changeIndex = ?, wallet = ? where id = ?")
void updateMixConfig(String scode, Boolean mixOnStartup, String mixToWalletFile, String mixToWalletName, Integer minMixes, int receiveIndex, int changeIndex, long wallet, long id); void updateMixConfig(String scode, Boolean mixOnStartup, String indexRange, String mixToWalletFile, String mixToWalletName, Integer minMixes, int receiveIndex, int changeIndex, long wallet, long id);
default void addMixConfig(Wallet wallet) { default void addMixConfig(Wallet wallet) {
if(wallet.getMixConfig() != null) { if(wallet.getMixConfig() != null) {
@ -32,10 +32,10 @@ public interface MixConfigDao {
} }
if(mixConfig.getId() == null) { if(mixConfig.getId() == null) {
long id = insertMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), mixConfig.getReceiveIndex(), mixConfig.getChangeIndex(), wallet.getId()); long id = insertMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixConfig.getIndexRange(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), mixConfig.getReceiveIndex(), mixConfig.getChangeIndex(), wallet.getId());
mixConfig.setId(id); mixConfig.setId(id);
} else { } else {
updateMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), mixConfig.getReceiveIndex(), mixConfig.getChangeIndex(), wallet.getId(), mixConfig.getId()); updateMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixConfig.getIndexRange(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), mixConfig.getReceiveIndex(), mixConfig.getChangeIndex(), wallet.getId(), mixConfig.getId());
} }
} }
} }

View file

@ -18,6 +18,7 @@ public class MixConfigMapper implements RowMapper<MixConfig> {
mixOnStartup = null; mixOnStartup = null;
} }
String indexRange = rs.getString("indexRange");
String mixToWalletFile = rs.getString("mixToWalletFile"); String mixToWalletFile = rs.getString("mixToWalletFile");
String mixToWalletName = rs.getString("mixToWalletName"); String mixToWalletName = rs.getString("mixToWalletName");
@ -26,7 +27,7 @@ public class MixConfigMapper implements RowMapper<MixConfig> {
minMixes = null; minMixes = null;
} }
MixConfig mixConfig = new MixConfig(scode, mixOnStartup, mixToWalletFile == null ? null : new File(mixToWalletFile), mixToWalletName, minMixes, rs.getInt("receiveIndex"), rs.getInt("changeIndex")); MixConfig mixConfig = new MixConfig(scode, mixOnStartup, indexRange, mixToWalletFile == null ? null : new File(mixToWalletFile), mixToWalletName, minMixes, rs.getInt("receiveIndex"), rs.getInt("changeIndex"));
mixConfig.setId(rs.getLong("id")); mixConfig.setId(rs.getLong("id"));
return mixConfig; return mixConfig;
} }

View file

@ -36,21 +36,24 @@ public interface WalletDao {
@CreateSqlObject @CreateSqlObject
UtxoMixDataDao createUtxoMixDataDao(); UtxoMixDataDao createUtxoMixDataDao();
@SqlQuery("select wallet.id, wallet.name, wallet.network, wallet.policyType, wallet.scriptType, wallet.storedBlockHeight, wallet.gapLimit, wallet.birthDate, policy.id, policy.name, policy.script from wallet left join policy on wallet.defaultPolicy = policy.id") @SqlQuery("select wallet.id, wallet.name, wallet.label, wallet.network, wallet.policyType, wallet.scriptType, wallet.storedBlockHeight, wallet.gapLimit, wallet.birthDate, policy.id, policy.name, policy.script from wallet left join policy on wallet.defaultPolicy = policy.id")
@RegisterRowMapper(WalletMapper.class) @RegisterRowMapper(WalletMapper.class)
List<Wallet> loadAllWallets(); List<Wallet> loadAllWallets();
@SqlQuery("select wallet.id, wallet.name, wallet.network, wallet.policyType, wallet.scriptType, wallet.storedBlockHeight, wallet.gapLimit, wallet.birthDate, policy.id, policy.name, policy.script from wallet left join policy on wallet.defaultPolicy = policy.id where wallet.id = 1") @SqlQuery("select wallet.id, wallet.name, wallet.label, wallet.network, wallet.policyType, wallet.scriptType, wallet.storedBlockHeight, wallet.gapLimit, wallet.birthDate, policy.id, policy.name, policy.script from wallet left join policy on wallet.defaultPolicy = policy.id where wallet.id = 1")
@RegisterRowMapper(WalletMapper.class) @RegisterRowMapper(WalletMapper.class)
Wallet loadMainWallet(); Wallet loadMainWallet();
@SqlQuery("select wallet.id, wallet.name, wallet.network, wallet.policyType, wallet.scriptType, wallet.storedBlockHeight, wallet.gapLimit, wallet.birthDate, policy.id, policy.name, policy.script from wallet left join policy on wallet.defaultPolicy = policy.id where wallet.id != 1") @SqlQuery("select wallet.id, wallet.name, wallet.label, wallet.network, wallet.policyType, wallet.scriptType, wallet.storedBlockHeight, wallet.gapLimit, wallet.birthDate, policy.id, policy.name, policy.script from wallet left join policy on wallet.defaultPolicy = policy.id where wallet.id != 1")
@RegisterRowMapper(WalletMapper.class) @RegisterRowMapper(WalletMapper.class)
List<Wallet> loadChildWallets(); List<Wallet> loadChildWallets();
@SqlUpdate("insert into wallet (name, network, policyType, scriptType, storedBlockHeight, gapLimit, birthDate, defaultPolicy) values (?, ?, ?, ?, ?, ?, ?, ?)") @SqlUpdate("insert into wallet (name, label, network, policyType, scriptType, storedBlockHeight, gapLimit, birthDate, defaultPolicy) values (?, ?, ?, ?, ?, ?, ?, ?, ?)")
@GetGeneratedKeys("id") @GetGeneratedKeys("id")
long insert(String name, int network, int policyType, int scriptType, Integer storedBlockHeight, Integer gapLimit, Date birthDate, long defaultPolicy); long insert(String name, String label, int network, int policyType, int scriptType, Integer storedBlockHeight, Integer gapLimit, Date birthDate, long defaultPolicy);
@SqlUpdate("update wallet set label = :label where id = :id")
void updateLabel(@Bind("id") long id, @Bind("label") String label);
@SqlUpdate("update wallet set storedBlockHeight = :blockHeight where id = :id") @SqlUpdate("update wallet set storedBlockHeight = :blockHeight where id = :id")
void updateStoredBlockHeight(@Bind("id") long id, @Bind("blockHeight") Integer blockHeight); void updateStoredBlockHeight(@Bind("id") long id, @Bind("blockHeight") Integer blockHeight);
@ -108,7 +111,7 @@ public interface WalletDao {
setSchema(schema); setSchema(schema);
createPolicyDao().addPolicy(wallet.getDefaultPolicy()); createPolicyDao().addPolicy(wallet.getDefaultPolicy());
long id = insert(truncate(wallet.getName()), wallet.getNetwork().ordinal(), wallet.getPolicyType().ordinal(), wallet.getScriptType().ordinal(), wallet.getStoredBlockHeight(), wallet.gapLimit(), wallet.getBirthDate(), wallet.getDefaultPolicy().getId()); long id = insert(truncate(wallet.getName()), truncate(wallet.getLabel()), wallet.getNetwork().ordinal(), wallet.getPolicyType().ordinal(), wallet.getScriptType().ordinal(), wallet.getStoredBlockHeight(), wallet.gapLimit(), wallet.getBirthDate(), wallet.getDefaultPolicy().getId());
wallet.setId(id); wallet.setId(id);
createKeystoreDao().addKeystores(wallet); createKeystoreDao().addKeystores(wallet);

View file

@ -17,6 +17,7 @@ public class WalletMapper implements RowMapper<Wallet> {
public Wallet map(ResultSet rs, StatementContext ctx) throws SQLException { public Wallet map(ResultSet rs, StatementContext ctx) throws SQLException {
Wallet wallet = new Wallet(rs.getString("wallet.name")); Wallet wallet = new Wallet(rs.getString("wallet.name"));
wallet.setId(rs.getLong("wallet.id")); wallet.setId(rs.getLong("wallet.id"));
wallet.setLabel(rs.getString("wallet.label"));
wallet.setNetwork(Network.values()[rs.getInt("wallet.network")]); wallet.setNetwork(Network.values()[rs.getInt("wallet.network")]);
wallet.setPolicyType(PolicyType.values()[rs.getInt("wallet.policyType")]); wallet.setPolicyType(PolicyType.values()[rs.getInt("wallet.policyType")]);
wallet.setScriptType(ScriptType.values()[rs.getInt("wallet.scriptType")]); wallet.setScriptType(ScriptType.values()[rs.getInt("wallet.scriptType")]);

View file

@ -1,5 +1,6 @@
package com.sparrowwallet.sparrow.wallet; package com.sparrowwallet.sparrow.wallet;
import com.samourai.whirlpool.client.wallet.beans.IndexRange;
import com.sparrowwallet.drongo.protocol.ScriptType; import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.drongo.wallet.MixConfig; import com.sparrowwallet.drongo.wallet.MixConfig;
import com.sparrowwallet.drongo.wallet.StandardAccount; import com.sparrowwallet.drongo.wallet.StandardAccount;
@ -14,6 +15,7 @@ import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox; import javafx.scene.control.ComboBox;
import javafx.scene.control.Spinner; import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory; import javafx.scene.control.SpinnerValueFactory;
import javafx.util.StringConverter;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
@ -31,6 +33,9 @@ public class MixToController implements Initializable {
@FXML @FXML
private Spinner<Integer> minMixes; private Spinner<Integer> minMixes;
@FXML
private ComboBox<IndexRange> indexRange;
private MixConfig mixConfig; private MixConfig mixConfig;
@Override @Override
@ -83,6 +88,35 @@ public class MixToController implements Initializable {
mixConfig.setMinMixes(newValue); mixConfig.setMinMixes(newValue);
EventManager.get().post(new MixToConfigChangedEvent(wallet)); EventManager.get().post(new MixToConfigChangedEvent(wallet));
}); });
indexRange.setConverter(new StringConverter<>() {
@Override
public String toString(IndexRange indexRange) {
if(indexRange == null) {
return "";
}
return indexRange.toString().charAt(0) + indexRange.toString().substring(1).toLowerCase();
}
@Override
public IndexRange fromString(String string) {
return null;
}
});
indexRange.setValue(IndexRange.FULL);
if(mixConfig.getIndexRange() != null) {
try {
indexRange.setValue(IndexRange.valueOf(mixConfig.getIndexRange()));
} catch(Exception e) {
//ignore
}
}
indexRange.valueProperty().addListener((observable, oldValue, newValue) -> {
mixConfig.setIndexRange(newValue.toString());
EventManager.get().post(new MixToConfigChangedEvent(wallet));
});
} }
public MixConfig getMixConfig() { public MixConfig getMixConfig() {

View file

@ -5,7 +5,6 @@ import com.google.common.eventbus.Subscribe;
import com.samourai.whirlpool.client.tx0.Tx0Preview; import com.samourai.whirlpool.client.tx0.Tx0Preview;
import com.sparrowwallet.drongo.BitcoinUnit; import com.sparrowwallet.drongo.BitcoinUnit;
import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.Network;
import com.sparrowwallet.drongo.SecureString; import com.sparrowwallet.drongo.SecureString;
import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.address.InvalidAddressException; import com.sparrowwallet.drongo.address.InvalidAddressException;
@ -381,9 +380,11 @@ public class UtxosController extends WalletFormController implements Initializab
mixConfig.setMixToWalletName(changedMixConfig.getMixToWalletName()); mixConfig.setMixToWalletName(changedMixConfig.getMixToWalletName());
mixConfig.setMixToWalletFile(changedMixConfig.getMixToWalletFile()); mixConfig.setMixToWalletFile(changedMixConfig.getMixToWalletFile());
mixConfig.setMinMixes(changedMixConfig.getMinMixes()); mixConfig.setMinMixes(changedMixConfig.getMinMixes());
mixConfig.setIndexRange(changedMixConfig.getIndexRange());
EventManager.get().post(new WalletMasterMixConfigChangedEvent(getWalletForm().getWallet())); EventManager.get().post(new WalletMasterMixConfigChangedEvent(getWalletForm().getWallet()));
Whirlpool whirlpool = AppServices.getWhirlpoolServices().getWhirlpool(getWalletForm().getWallet()); Whirlpool whirlpool = AppServices.getWhirlpoolServices().getWhirlpool(getWalletForm().getWallet());
whirlpool.setPostmixIndexRange(mixConfig.getIndexRange());
try { try {
String mixToWalletId = AppServices.getWhirlpoolServices().getWhirlpoolMixToWalletId(mixConfig); String mixToWalletId = AppServices.getWhirlpoolServices().getWhirlpoolMixToWalletId(mixConfig);
whirlpool.setMixToWallet(mixToWalletId, mixConfig.getMinMixes()); whirlpool.setMixToWallet(mixToWalletId, mixConfig.getMinMixes());

View file

@ -510,6 +510,13 @@ public class WalletForm {
} }
} }
@Subscribe
public void walletLabelChanged(WalletLabelChangedEvent event) {
if(event.getWallet() == wallet) {
Platform.runLater(() -> EventManager.get().post(new WalletDataChangedEvent(wallet)));
}
}
@Subscribe @Subscribe
public void walletGapLimitChanged(WalletGapLimitChangedEvent event) { public void walletGapLimitChanged(WalletGapLimitChangedEvent event) {
if(event.getWallet() == wallet) { if(event.getWallet() == wallet) {

View file

@ -111,7 +111,7 @@ public class Whirlpool {
WhirlpoolWalletConfig whirlpoolWalletConfig = new WhirlpoolWalletConfig(dataSourceFactory, httpClientService, stompClientService, torClientService, serverApi, whirlpoolServer.getParams(), false); WhirlpoolWalletConfig whirlpoolWalletConfig = new WhirlpoolWalletConfig(dataSourceFactory, httpClientService, stompClientService, torClientService, serverApi, whirlpoolServer.getParams(), false);
whirlpoolWalletConfig.setDataPersisterFactory(dataPersisterFactory); whirlpoolWalletConfig.setDataPersisterFactory(dataPersisterFactory);
whirlpoolWalletConfig.setPartner("SPARROW"); whirlpoolWalletConfig.setPartner("SPARROW");
whirlpoolWalletConfig.setIndexRangePostmix(Config.get().getPostmixIndexRange()); whirlpoolWalletConfig.setIndexRangePostmix(IndexRange.FULL);
return whirlpoolWalletConfig; return whirlpoolWalletConfig;
} }
@ -470,6 +470,16 @@ public class Whirlpool {
this.resyncMixesDone = resyncMixesDone; this.resyncMixesDone = resyncMixesDone;
} }
public void setPostmixIndexRange(String indexRange) {
if(indexRange != null) {
try {
config.setIndexRangePostmix(IndexRange.valueOf(indexRange));
} catch(Exception e) {
log.error("Invalid index range " + indexRange);
}
}
}
public void setMixToWallet(String mixToWalletId, Integer minMixes) { public void setMixToWallet(String mixToWalletId, Integer minMixes) {
if(mixToWalletId == null) { if(mixToWalletId == null) {
config.setExternalDestination(null); config.setExternalDestination(null);

View file

@ -89,6 +89,10 @@ public class WhirlpoolServices {
} }
} }
if(wallet.getMasterMixConfig() != null) {
whirlpool.setPostmixIndexRange(wallet.getMasterMixConfig().getIndexRange());
}
Whirlpool.StartupService startupService = whirlpool.createStartupService(); Whirlpool.StartupService startupService = whirlpool.createStartupService();
startupService.setPeriod(Duration.minutes(2)); startupService.setPeriod(Duration.minutes(2));
startupService.setOnSucceeded(workerStateEvent -> { startupService.setOnSucceeded(workerStateEvent -> {

View file

@ -0,0 +1,2 @@
alter table wallet add column label varchar(255) after name;
alter table mixConfig add column indexRange varchar(10) after mixOnStartup;

View file

@ -3,13 +3,16 @@
<?import java.lang.*?> <?import java.lang.*?>
<?import java.util.*?> <?import java.util.*?>
<?import javafx.scene.*?> <?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import tornadofx.control.Form?> <?import tornadofx.control.Form?>
<?import tornadofx.control.Fieldset?> <?import tornadofx.control.Fieldset?>
<?import tornadofx.control.Field?> <?import tornadofx.control.Field?>
<?import com.sparrowwallet.sparrow.control.HelpLabel?> <?import com.sparrowwallet.sparrow.control.HelpLabel?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Spinner?>
<?import com.samourai.whirlpool.client.wallet.beans.IndexRange?>
<BorderPane stylesheets="@../general.css" styleClass="line-border" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.wallet.MixToController"> <BorderPane stylesheets="@../general.css" styleClass="line-border" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.wallet.MixToController">
<center> <center>
@ -36,6 +39,23 @@
</Field> </Field>
</Fieldset> </Fieldset>
</Form> </Form>
<Form GridPane.columnIndex="0" GridPane.rowIndex="1">
<Fieldset inputGrow="SOMETIMES" text="Postmix Wallet Settings">
<Field text="Index range:">
<ComboBox fx:id="indexRange" prefWidth="140">
<items>
<FXCollections fx:factory="observableArrayList">
<IndexRange fx:constant="FULL" />
<IndexRange fx:constant="EVEN" />
<IndexRange fx:constant="ODD" />
</FXCollections>
</items>
</ComboBox>
<HelpLabel helpText="Using different index ranges allows the same wallet to be mixed simultaneously on multiple clients.\nSelect Full if simultaneous mixing is not required to keep wallet indexing compact for quicker load times.\nSelect Even to mix on the Samourai mobile app simultaneously.\nSelect Odd to mix on Samourai CLI/GUI simultaneously."/>
</Field>
</Fieldset>
</Form>
</GridPane> </GridPane>
</center> </center>
</BorderPane> </BorderPane>