Compare commits

...
237 Commits
Author SHA1 Message Date
tobtoht 8c197f26ea Merge pull request 'build: prepare beta-2' (#224) from tobtoht/feather:beta-2 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/224
2020-12-14 23:06:10 +00:00
tobtoht 6f17a1dfaa Merge pull request 'Update OpenSSL to 1.1.1i' (#223) from tobtoht/feather:openssl_1.1.1i into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/223
2020-12-14 23:04:58 +00:00
tobtoht 2217ae602a Merge pull request 'Allow resending failed transactions' (#212) from tobtoht/feather:black_holed_no_more into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/212
2020-12-14 22:27:12 +00:00
tobtoht 75743e8897 build: prepare beta-2 2020-12-14 23:10:54 +01:00
tobtoht 169d14ab3a Allow resending failed transactions 2020-12-14 23:07:50 +01:00
tobtoht 710556a580 Update OpenSSL to 1.1.1i 2020-12-14 21:55:52 +01:00
tobtoht 15211ce5fa Merge pull request 'Menu: add rescan spent' (#221) from tobtoht/feather:rescan_spent into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/221
2020-12-14 19:45:26 +00:00
tobtoht 66f53d865e Menu: add rescan spent 2020-12-14 20:44:37 +01:00
tobtoht ea81b308f7 Merge pull request 'TxInfoDialog: set blockheight to unconfirmed for mempool txs' (#220) from tobtoht/feather:tx_info_blockheight into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/220
2020-12-14 19:31:01 +00:00
tobtoht 9016fa13dc TxInfoDialog: set blockheight to unconfirmed for mempool txs 2020-12-14 20:30:15 +01:00
tobtoht cee70a997d Merge pull request 'TickerWidget: don't show percentage on balance' (#219) from tobtoht/feather:ticker_widget_no_perc into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/219
2020-12-14 19:19:40 +00:00
tobtoht 041c11f618 TickerWidget: don't show percentage on balance 2020-12-14 20:17:22 +01:00
tobtoht c5f0962e40 Merge pull request 'Replace showMessageBox with Qt builtin' (#218) from tobtoht/feather:messagebox_cleanup into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/218
2020-12-14 02:25:11 +00:00
tobtoht 85a06007a1 Replace showMessageBox with Qt builtin 2020-12-14 03:23:19 +01:00
tobtoht b6459d1b64 Merge pull request 'Remove user_agents.txt' (#217) from tobtoht/feather:remove_user_agents into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/217
2020-12-14 01:49:06 +00:00
tobtoht 653e59f5ec Remove user_agents.txt 2020-12-14 02:47:51 +01:00
tobtoht 71e28831d8 Merge pull request 'Coins: copy label' (#216) from tobtoht/feather:coins_copy_label into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/216
2020-12-14 01:33:29 +00:00
tobtoht 874748ea7f Coins: copy label 2020-12-14 02:30:30 +01:00
tobtoht d3e55c4510 Merge pull request 'Store wallet immediately after sending tx' (#215) from tobtoht/feather:store_on_send into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/215
2020-12-14 01:18:08 +00:00
tobtoht 147ee8ef8b Store wallet immediately after sending tx 2020-12-14 02:15:56 +01:00
tobtoht 5ec641bc6f Merge pull request 'Update fiat conversion label on donate' (#214) from tobtoht/feather:donation_fix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/214
2020-12-14 01:01:00 +00:00
tobtoht 4a37be1ce7 Update fiat conversion label on donate 2020-12-14 01:59:32 +01:00
tobtoht d1b4db2be4 Merge pull request 'Core: rebase to v0.17.1.7' (#213) from tobtoht/feather:v0.17.1.7 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/213
2020-12-13 13:21:29 +00:00
tobtoht 1e2fa51b98 Core: rebase to v0.17.1.7 2020-12-13 14:19:17 +01:00
tobtoht 743c5fa9a4 Merge pull request 'DebugInfoDialog: improve Tor status on Tails' (#211) from tobtoht/feather:tails_debug_info into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/211
2020-12-12 16:34:58 +00:00
tobtoht ae1d6a2d1c DebugInfoDialog: improve Tor status on Tails 2020-12-12 17:33:33 +01:00
tobtoht 5e246519c2 Merge pull request 'SeedDialog: improve UI' (#210) from tobtoht/feather:seed_dialog_height into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/210
2020-12-12 16:23:24 +00:00
tobtoht 8b5cb8ba2c SeedDialog: improve UI 2020-12-12 17:19:37 +01:00
tobtoht 3ea7e5932e Merge pull request 'Menu: remove disabled open wallet item' (#209) from tobtoht/feather:remove_open_wallet into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/209
2020-12-12 16:07:29 +00:00
tobtoht 97b4fcb958 Menu: remove disable open wallet item 2020-12-12 16:59:44 +01:00
tobtoht 80c1c66bea Merge pull request 'MorphToken: add statustext for missing states' (#208) from tobtoht/feather:morphtoken_processing_delay into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/208
2020-12-12 15:37:26 +00:00
tobtoht be61c803bf MorphToken: add statustext for missing states 2020-12-12 16:35:44 +01:00
tobtoht a0a307f3bd Merge pull request 'Remove sorry()' (#207) from tobtoht/feather:no_sorry into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/207
2020-12-12 14:56:18 +00:00
tobtoht 1d8f4f0bfd Remove sorry() 2020-12-12 15:54:43 +01:00
tobtoht 7c288570b1 Merge pull request 'Update calc icon' (#206) from tobtoht/feather:calc_icon into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/206
2020-12-12 14:48:57 +00:00
tobtoht 02d71ebf02 Update calc icon 2020-12-12 15:46:41 +01:00
tobtoht 6ef4eaa39f Merge pull request 'Rename XMRig tab to Mining' (#205) from tobtoht/feather:xmrig_mining into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/205
2020-12-12 14:29:30 +00:00
tobtoht d3ee2744d4 Merge pull request 'XMRig: squish settings UI' (#204) from tobtoht/feather:xmrig_cleanup into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/204
2020-12-12 14:24:02 +00:00
tobtoht 61b54efb97 Rename XMRig tab to Mining 2020-12-12 15:22:31 +01:00
tobtoht 91b00da4af XMRig: squish settings UI 2020-12-12 14:39:13 +01:00
tobtoht 2b72624ec0 Merge pull request 'Consolidate exchanges to exchange tab' (#203) from tobtoht/feather:consolidate_exchanges into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/203
2020-12-12 13:03:06 +00:00
tobtoht 55bb304dc2 Merge pull request 'Drone: optimize builds' (#202) from tobtoht/feather:drone_optimize_builds into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/202
2020-12-12 12:18:18 +00:00
tobtoht 8ffd2293f4 Consolidate exchanges to exchange tab 2020-12-12 02:49:33 +01:00
tobtoht 3df2e591fe Drone: optimize builds 2020-12-12 01:54:04 +01:00
tobtoht 785771cb90 Merge pull request 'Do not bundle XMRig' (#201) from tobtoht/feather:xmrip into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/201
2020-12-12 00:51:55 +00:00
tobtoht aa14a2dcbb Do not bundle XMRig binary 2020-12-12 01:18:09 +01:00
tobtoht c9e2ce3770 Merge pull request 'Spell it backwards' (#200) from tobtoht/feather:tobtoht into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/200
2020-12-11 19:50:08 +00:00
tobtoht 835e4aaca3 Spell it backwards 2020-12-11 20:46:24 +01:00
tobtoht 97900bcbe6 Merge pull request 'Home: add tabs for home widgets' (#199) from tobtoht/feather:main_tab into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/199
2020-12-11 13:33:32 +00:00
tobtoht a9ec69afd0 Home: add tabs for home widgets 2020-12-11 14:32:14 +01:00
tobtoht a008f1f45f Merge pull request 'Add reproducible build instructions' (#198) from tobtoht/feather:update_building into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/198
2020-12-10 17:16:54 +00:00
tobtoht fbd6b8eb53 Add reproducible build instructions 2020-12-10 18:13:21 +01:00
tobtoht 855755fea3 Merge pull request 'Add release signing key' (#197) from tobtoht/feather:signing_key into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/197
2020-12-09 21:14:31 +00:00
tobtoht 302e585af4 Add release signing key 2020-12-09 22:12:55 +01:00
tobtoht 9592335fa1 Merge pull request 'Update alpha message' (#196) from tobtoht/feather:beta_warning into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/196
2020-12-09 20:18:30 +00:00
tobtoht c874220b4e Update alpha message 2020-12-09 21:14:19 +01:00
tobtoht 5d792ddf4c Merge pull request 'build: prepare beta-1' (#193) from tobtoht/feather:beta-1 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/193
2020-12-09 19:20:03 +00:00
tobtoht e942685c23 Merge pull request 'Drone: update signature' (#195) from tobtoht/feather:drone_sign into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/195
2020-12-09 12:14:40 +00:00
tobtoht 11800bec35 Drone: update signature 2020-12-09 13:03:16 +01:00
tobtoht 1b1bb7d76d build: prepare beta-1 2020-12-09 12:56:39 +01:00
tobtoht 394ff96aa2 Merge pull request 'Drone: add mac builds' (#194) from tobtoht/feather:mac_builds into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/194
2020-12-09 00:57:33 +00:00
tobtoht 34c1ef6126 Drone: add mac builds 2020-12-09 01:55:43 +01:00
tobtoht 58af196f84 Merge pull request 'Windows: write to console' (#191) from tobtoht/feather:windows_console_output into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/191
2020-12-08 17:15:56 +00:00
tobtoht 564ec31c2d Windows: write to console 2020-12-08 17:37:20 +01:00
tobtoht 0f96dd7fb5 Merge pull request 'Fix CI' (#192) from tobtoht/feather:tobtoht-patch-9 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/192
2020-12-08 16:11:43 +00:00
tobtohtandtobtoht f42fb96b9d Fix CI 2020-12-08 16:47:47 +01:00
SmashTRandtobtoht 8401b79bf9 Shortcut for update balance (#184)
Fixed small mistake

Merge branch 'master' into master

Shortcut for update balance

Reviewed-on: https://git.wownero.com/feather/feather/pulls/184
2020-12-07 23:26:48 +00:00
tobtoht c4c8a43eb7 Merge pull request 'Remove torsocks submodule and misc unused files' (#186) from tobtoht/feather:remove_torsocks into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/186
2020-12-07 21:11:48 +00:00
tobtoht ecc88e1d48 Merge pull request 'Update Dockerfile for Qt 5.15.2' (#185) from tobtoht/feather:qt_5_15_2 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/185
2020-12-07 21:01:56 +00:00
tobtoht b73233df77 Merge pull request 'Core: rebase to v0.17.1.6' (#190) from tobtoht/feather:v0.17.1.6 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/190
2020-12-07 16:59:31 +00:00
tobtoht f94d4e6bb2 Core: rebase to v0.17.1.6 2020-12-07 17:57:29 +01:00
tobtoht 6cfd0794eb Update Dockerfile for Qt 5.15.2 2020-12-05 18:28:08 +01:00
tobtoht 42a64f9b0a Remove torsocks submodule and misc unused files 2020-12-05 18:13:08 +01:00
tobtoht 33a85e1bd8 Merge pull request 'Update PKGBUILD' (#182) from tobtoht/feather:pkgbuild into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/182
2020-11-30 19:41:27 +00:00
tobtoht fde578aac9 Update PKGBUILD 2020-11-30 20:22:53 +01:00
tobtoht 925ef56830 Merge pull request 'Core: rebase to v0.17.1.5.' (#181) from tobtoht/feather:v0.17.1.5 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/181
2020-11-30 16:13:57 +00:00
tobtoht 585c850dd5 Core: rebase to v0.17.1.5. 2020-11-30 14:48:07 +01:00
tobtoht 72f33da508 Merge pull request 'Improve row background color contrast for QDarkStyle' (#179) from tobtoht/feather:darkstyle_readability into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/179
2020-11-25 21:26:39 +00:00
tobtoht 480ecfd047 Improve row background color contrast for QDarkStyle 2020-11-25 22:09:13 +01:00
tobtoht 1a6024c697 Merge pull request 'MorphToken: Add Qr code for deposit address' (#178) from tobtoht/feather:morphtoken_qr into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/178
2020-11-25 20:57:33 +00:00
tobtoht a11dd576e4 MorphToken: Add Qr code for deposit address 2020-11-25 21:44:59 +01:00
tobtoht 9fed3eb171 Merge pull request 'update PKGBUILD' (#177) from wowario/feather:master into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/177
2020-11-25 20:36:40 +00:00
wowario 20156a7440 update PKGBUILD 2020-11-25 23:33:43 +03:00
tobtoht ca5b1df7df Merge pull request 'XMRig: don't disable mining on Tails' (#176) from tobtoht/feather:xmrig_mining_tails into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/176
2020-11-25 17:38:41 +00:00
tobtoht 474ee2100c XMRig: don't disable mining on Tails 2020-11-25 17:16:10 +01:00
tobtoht 1ccedea1dd Merge pull request 'Settings: temporarily remove warn on update checkbox' (#175) from tobtoht/feather:settings_update into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/175
2020-11-25 15:29:46 +00:00
tobtoht 70dd25c477 Settings: temporarily remove warn on update checkbox
Update checking will be back after the alpha
2020-11-25 15:23:23 +01:00
tobtoht bce983a6a5 Merge pull request 'Menu: add shortcuts' (#174) from tobtoht/feather:shortcuts into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/174
2020-11-25 14:18:12 +00:00
tobtoht eb8d150a9d Menu: add shortcuts 2020-11-25 14:35:28 +01:00
tobtoht 841739cee9 Merge pull request 'SeedDialog: show restore height for 25 word seeds' (#173) from tobtoht/feather:seed_restore_height into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/173
2020-11-25 12:11:31 +00:00
tobtoht d4dbc748c8 SeedDialog: show restore height for 25 word seeds 2020-11-25 12:56:01 +01:00
tobtoht 5ce6c8933d Merge pull request 'MorphToken: get rates' (#171) from tobtoht/feather:morphtoken_rates into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/171
2020-11-25 11:35:16 +00:00
tobtoht f61355c409 MorphToken: get rates 2020-11-25 12:00:09 +01:00
tobtoht edad1928ab Merge pull request 'TickerWidget: Format fiat currency using locale' (#170) from tobtoht/feather:ticker_locale into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/170
2020-11-24 22:29:45 +00:00
tobtoht 4201167477 TickerWidget: Format fiat currency using locale 2020-11-24 23:10:50 +01:00
tobtoht 16414ba2e9 Merge pull request 'Send: Always include pref. currency in combobox' (#169) from tobtoht/feather:send_pref_cur into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/169
2020-11-24 21:26:37 +00:00
tobtoht 1d001322cc Send: Always include pref. currency in combobox 2020-11-24 22:16:24 +01:00
tobtoht 9d781d1b57 Merge pull request 'VerifyProofDialog: minor fixes' (#166) from tobtoht/feather:tx_proof_width into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/166
2020-11-24 20:17:55 +00:00
tobtoht 3453e5ef34 Merge pull request 'WalletInfoDialog: fix open wallet directory on macOS' (#168) from tobtoht/feather:open_url into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/168
2020-11-24 20:17:44 +00:00
tobtoht 76da957b81 Merge pull request 'Settings: raise window' (#167) from tobtoht/feather:settings_bring_to_front into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/167
2020-11-24 20:17:24 +00:00
tobtoht 35438792a0 Settings: raise window 2020-11-24 21:16:14 +01:00
tobtoht 01966df866 WalletInfoDialog: fix open wallet directory on macOS 2020-11-24 21:02:22 +01:00
tobtoht e2eb32ce78 VerifyProofDialog: minor fixes
- Fix layout issue on macOS
- Simplify button logic
- Set verify button to default
2020-11-24 20:27:00 +01:00
tobtoht 03f484c2ae Merge pull request 'PasswordDialog: show warning if password incorrect' (#165) from tobtoht/feather:incorrect_password into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/165
2020-11-24 17:16:07 +00:00
tobtoht c44ee73ed0 PasswordDialog: show warning if password incorrect 2020-11-24 15:16:20 +01:00
tobtoht e6e669845c Merge pull request 'Misc networking fixes' (#160) from tobtoht/feather:nodes into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/160
2020-11-23 17:19:30 +00:00
tobtoht 5a08bc353e Misc networking fixes
- connecting to nodes is much faster and more reliable now
- reduced the amount of spaghetti in libwalletqt and greatly simplified the logic in nodes.cpp
- Settings -> Node dialog should feel slightly more responsive
- during synchronization the status bar will now display the amount of data downloaded
- fixed some edge cases that could cause unreasonably long hangs
- Help -> Debug Info screen now auto-updates every 5 seconds
- Don't use SSL over Tor
2020-11-23 17:57:42 +01:00
tobtoht c8bc66a287 Merge pull request 'DebugInfoDialog: add target height' (#159) from tobtoht/feather:target-height into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/159
2020-11-17 22:43:19 +00:00
tobtoht 3beb470bbd DebugInfoDialog: add target height 2020-11-17 23:40:46 +01:00
tobtoht b875ee362e Merge pull request 'Menu: remove About QT' (#157) from tobtoht/feather:about_qt into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/157
2020-11-14 22:17:31 +00:00
tobtoht 4e3a977995 Menu: remove About QT
bloat
2020-11-14 23:15:05 +01:00
tobtoht eb801ed9d4 Merge pull request 'Mitigate target_height denial of service attack in wsMode' (#156) from tobtoht/feather:target_height into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/156
2020-11-14 21:55:36 +00:00
tobtoht d9dfef021f Mitigate target_height attack 2020-11-14 22:42:41 +01:00
tobtoht d2d3978de6 Change websocket .onion 2020-11-14 22:40:10 +01:00
tobtoht 02f7249e6e Merge pull request 'Revert "Syncing hotfix"' (#154) from tobtoht/feather:sync_hotfix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/154
2020-11-14 15:16:13 +00:00
tobtoht a3309cea91 Revert "Syncing hotfix"
This reverts commit 4f56147319.
2020-11-14 16:15:00 +01:00
tobtoht 137ef6da72 Merge pull request 'Syncing hotfix' (#153) from tobtoht/feather:sync_hotfix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/153
2020-11-14 14:48:11 +00:00
tobtoht 4f56147319 Syncing hotfix 2020-11-14 15:39:29 +01:00
tobtoht d58259cefe Merge pull request 'Receive: Fix qr code segfault' (#152) from tobtoht/feather:qr_code_crash into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/152
2020-11-14 11:17:04 +00:00
tobtoht 9be79bba48 Receive: Fix qr code segfault 2020-11-14 12:11:54 +01:00
tobtoht 64db32dca9 Wallet: do not emit updated on refresh 2020-11-14 12:01:45 +01:00
tobtoht 774b4ed15f Merge pull request 'DebugInfoDialog: make some text selectable' (#151) from tobtoht/feather:text_select into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/151
2020-11-14 10:32:13 +00:00
tobtoht d337653e53 DebugInfoDialog: make some text selectable 2020-11-14 11:31:28 +01:00
tobtoht b06b7fca2a Merge pull request 'Add missing license headers' (#150) from tobtoht/feather:missing_licence into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/150
2020-11-14 10:27:31 +00:00
tobtoht 169720002c Add missing license headers 2020-11-14 11:26:37 +01:00
tobtoht d7135393cd Merge pull request 'PasswordDialog: misc improvements' (#149) from tobtoht/feather:password_dialog into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/149
2020-11-14 10:06:20 +00:00
tobtoht 1e4a442b16 PasswordDialog: misc improvements 2020-11-14 10:57:06 +01:00
tobtoht 519df3f5a1 Merge pull request 'Nodes: don't connect to out of sync nodes in wsmode' (#148) from tobtoht/feather:node_height_mode into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/148
2020-11-12 20:19:52 +00:00
tobtoht 2a03ca9eda Nodes: don't connect to out of sync nodes in wsmode 2020-11-12 21:03:36 +01:00
tobtoht ff5dff26bb Merge pull request 'SeedDialog: add 25 word seed toggle' (#147) from tobtoht/feather:seed_25 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/147
2020-11-11 22:12:47 +00:00
tobtoht cbd29e6290 Merge pull request 'MorphToken: allow disabling module' (#146) from tobtoht/feather:morphtoken into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/146
2020-11-11 22:11:01 +00:00
tobtoht 0f3c005b60 SeedDialog: add 25 word seed toggle 2020-11-11 23:09:35 +01:00
tobtoht 39c1d3bbf7 MorphToken: allow disabling module 2020-11-11 22:42:48 +01:00
tobtoht b66aceccc8 Merge pull request 'Initial MorphToken support' (#145) from tobtoht/feather:morphtoken into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/145
2020-11-11 16:04:35 +00:00
tobtoht e9a4a828d6 Initial MorphToken support 2020-11-11 16:51:12 +01:00
tobtoht bd60e30c3f Merge pull request 'Import transaction' (#143) from tobtoht/feather:import_tx into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/143
2020-11-10 11:48:11 +00:00
tobtoht 046b2cfc4c Import transaction 2020-11-10 12:38:37 +01:00
tobtoht 24133ac390 Merge pull request 'History: don't show copy spend proof on incoming transactions' (#115) from mrdeveloper/feather:hide-spend-proof-incoming-tx into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/115
2020-11-08 12:09:13 +00:00
tobtoht 8aecf79647 Merge pull request 'TransactionInfoDialog: add copy spendproof, in/outproof' (#142) from tobtoht/feather:txproof into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/142
2020-11-08 12:00:32 +00:00
tobtoht 780a35fabe TransactionInfoDialog: add copy spendproof, in/outproof 2020-11-08 12:12:06 +01:00
mrdeveloper 0e7c773bfd Remove unused declared method 2020-11-08 10:13:37 +01:00
mrdeveloper 11f8406be3 History: don't show copy spend proof on incoming transactions 2020-11-08 10:13:37 +01:00
tobtoht 2c99454565 Merge pull request 'FutureScheduler: update with upstream v0.17.1.3' (#141) from tobtoht/feather:scheduler into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/141
2020-11-08 07:37:30 +00:00
tobtoht cd96abe545 FutureScheduler: update with upstream v0.17.1.3 2020-11-08 08:35:18 +01:00
tobtoht d76b688ec4 Merge pull request 'Libwalletqt: update with upstream' (#140) from tobtoht/feather:libwalletqt_syncing into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/140
2020-11-08 07:16:57 +00:00
tobtoht ed47e8e05c Merge pull request 'Added cryptonote-social mining pool to XMRig' (#136) from mrdeveloper/feather:cryptonote-social into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/136
2020-11-08 07:09:55 +00:00
tobtoht 268b87a803 Libwalletqt: update with upstream 2020-11-08 08:07:05 +01:00
tobtoht 318690681b Merge pull request 'Update for v0.17.1.3' (#139) from tobtoht/feather:v0.17.1.3 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/139
2020-11-08 06:40:08 +00:00
tobtoht b1e37e714d Update for v0.17.1.3 2020-11-08 07:36:20 +01:00
mrdeveloper 18b514351d Added cryptonote-social mining pool to XMRig 2020-11-03 13:59:32 +01:00
tobtoht 63c120bdb0 Merge pull request 'Stylesheets: Breeze: misc fixes' (#135) from tobtoht/feather:stylesheet_breeze_fixes into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/135
2020-11-02 14:21:11 +00:00
tobtoht 96409ecc17 Stylesheets: Breeze: misc fixes 2020-11-02 15:20:11 +01:00
tobtoht c1cba44cba Merge pull request 'AppContext: updateBalance: don't throw runtime error' (#134) from tobtoht/feather:no_runtime_error into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/134
2020-11-02 10:03:59 +00:00
tobtoht 7a1ac42b1e AppContext: updateBalance: don't throw runtime error 2020-11-02 11:03:08 +01:00
tobtoht 87fd142ffd Merge pull request 'Settings: add hide balance feature' (#133) from tobtoht/feather:hide_balance into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/133
2020-11-02 09:38:50 +00:00
tobtoht 62ad0d9527 Settings: add hide balance feature 2020-11-02 10:37:36 +01:00
tobtoht 4f9e4ac93d Merge pull request 'Utils: add blockchair.com block explorer' (#132) from tobtoht/feather:blockchair into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/132
2020-11-02 09:12:35 +00:00
tobtoht cb6f2873a9 Utils: add blockchair.com block explorer 2020-11-02 10:11:37 +01:00
tobtoht 20b741d30d Merge pull request 'Coins: numerical sort for amount column' (#105) from tobtoht/feather:coins_amount_sort into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/105
2020-11-02 07:58:50 +00:00
tobtoht 7ed2ff15d5 Merge pull request 'CCSWidget: fix misspelling' (#131) from tobtoht/feather:fix_ccs into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/131
2020-11-02 07:56:41 +00:00
tobtoht da4b2d16ef CCSWidget: fix misspelling 2020-11-02 08:52:20 +01:00
tobtoht 4521223413 Merge pull request 'Simplify and remove white space on recipient (Pay to)' (#124) from mrdeveloper/feather:simplified-recipient-addr into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/124
Reviewed-by: tobtoht <tobtoht@noreply.gitgud.wownero.nl>
2020-10-30 21:17:42 +00:00
mrdeveloper 0dd81c4873 Simplify and remove white space on recipient (Pay to) 2020-10-30 22:13:56 +01:00
dsc df2ff26c0f Merge pull request 'MacOS: add touchbar support' (#121) from dsc/feather:macos-touchbar-submodule into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/121
2020-10-28 22:23:49 +00:00
mrdeveloperanddsc e657e2a6b0 MacOS: add touchbar support
Co-Authored-By: dsc <dsc@xmr.pm>
2020-10-28 21:35:18 +01:00
dsc 34a63897d6 Merge pull request 'BugFix: show message box if no wallet is selected' (#118) from mrdeveloper/feather:bug-wallet-select into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/118
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-26 16:18:26 +00:00
dsc 6279591d1b Merge pull request 'Check if given node URL has https so we can append https for get_info call' (#120) from mrdeveloper/feather:node-check-for-https into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/120
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-26 15:36:36 +00:00
mrdeveloper 403b8140b3 Check if given node URL has https so we can append https for get_info call 2020-10-25 09:16:29 +01:00
mrdeveloper 71ba9f6d4a BugFix: show message box if no wallet is selected 2020-10-23 19:57:06 +02:00
dsc 3d5dae1f42 Merge pull request 'Coins: disable sweep instead of hide when output unconfirmed' (#111) from tobtoht/feather:coins_hide_sweep into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/111
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-21 23:41:46 +00:00
tobtoht 78eabc5ae7 Coins: disable sweep instead of hide when output unconfirmed
Suggested by moneroarbo
2020-10-21 21:53:51 +02:00
dsc 485fb89941 Merge pull request 'Include QtMultimedia for buildbots' (#108) from dsc/feather:include-qtmultimedia into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/108
Reviewed-by: tobtoht <tobtoht@noreply.gitgud.wownero.nl>
2020-10-21 17:27:05 +00:00
dsc df280cdd91 Merge pull request 'Write proper .exe on Windows' (#109) from dsc/feather:write-exe-windows into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/109
Reviewed-by: tobtoht <tobtoht@noreply.gitgud.wownero.nl>
2020-10-21 16:11:11 +00:00
dsc 9b96ece2f9 Merge pull request 'XMRig: Donate level 1' (#110) from dsc/feather:xmrig-donate-level into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/110
Reviewed-by: tobtoht <tobtoht@noreply.gitgud.wownero.nl>
2020-10-21 16:10:58 +00:00
dsc a44087b750 XMRig: Donate level 1
Signed-off-by: dsc <dsc@xmr.pm>
2020-10-21 18:06:31 +02:00
dsc 70cbf59ce8 Write proper .exe on Windows
Signed-off-by: dsc <dsc@xmr.pm>
2020-10-21 17:56:39 +02:00
dsc 4aeaf2660f Include QtMultimedia for buildbots
Signed-off-by: dsc <dsc@xmr.pm>
2020-10-21 17:46:51 +02:00
tobtoht 9b7849c5be Coins: numerical sort for amount column 2020-10-21 16:57:06 +02:00
tobtoht 51a0f86652 Move cdiv to globals.h 2020-10-21 16:57:03 +02:00
dsc fa6ee35fb0 Merge pull request 'Mainwindow: fix tab order and stylization' (#104) from tobtoht/feather:tabs_order into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/104
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-21 12:25:46 +00:00
tobtoht b1160280fe Mainwindow: fix tab order and stylization 2020-10-21 13:27:39 +02:00
tobtoht 7441d6cb4a Merge pull request 'XMRig: fix stop on windows' (#102) from tobtoht/feather:xmrrig_stop_windows into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/102
2020-10-21 10:37:32 +00:00
mrdeveloper 23000c6e60 Merge pull request 'PasswordDialog: Show wallet name' (#103) from mrdeveloper/feather:password-dialog-show-wallet-name into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/103
Reviewed-by: tobtoht <tobtoht@noreply.gitgud.wownero.nl>
2020-10-21 10:26:33 +00:00
mrdeveloper 75edc6e5bb Merge branch 'master' into password-dialog-show-wallet-name 2020-10-21 12:21:10 +02:00
mrdeveloper 06f649cbb7 Merge pull request 'Contacts: import via csv file' (#100) from mrdeveloper/feather:contacts-import-csv into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/100
Reviewed-by: tobtoht <tobtoht@noreply.gitgud.wownero.nl>
2020-10-21 10:19:43 +00:00
tobtoht ff78b5a6c2 XMRig: fix stop on windows 2020-10-21 12:11:10 +02:00
mrdeveloper 47d965c6cd Make format csv import as same as export 2020-10-21 10:10:48 +02:00
mrdeveloper d6c26d4159 PasswordDialog: Show wallet name 2020-10-21 08:45:25 +02:00
mrdeveloper 78516f4546 Contacts: import via csv file 2020-10-21 08:25:02 +02:00
dsc 49f072eea4 Merge pull request 'TransactionInfoDialog: add tx key' (#96) from tobtoht/feather:tx_key into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/96
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-20 13:19:59 +00:00
tobtoht 302c258e6b TransactionInfoDialog: add tx key 2020-10-20 01:11:15 +02:00
dsc 70f1846de6 Merge pull request 'Update for v0.17.1.1' (#92) from tobtoht/feather:v0.17.1.1 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/92
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-19 00:51:10 +00:00
tobtoht ae2815c1c6 Update for v0.17.1.1 2020-10-19 02:20:02 +02:00
dsc 24993bc0b2 Merge pull request 'Offline transaction signing' (#88) from tobtoht/feather:offline_tx_signing into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/88
Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
2020-10-19 00:09:36 +00:00
tobtoht 216b2e0c5e Offline transaction signing 2020-10-19 01:39:23 +02:00
dsc 44a2fc30dc Merge pull request 'Cmake: Refactor executable embeds, embed XMRig, allow solo mining' (#89) from dsc/feather:refactor-feather-execs into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/89
2020-10-18 20:47:53 +00:00
dsc aee60f33b7 - Embed XMRig executable (baked into buildbot image)
- Refactored CMake related to Tor/XMRig
- Move executables to `src/assets/exec`
- Embedding executables require passing definition to CMake, e.g:
  - `-DTOR=/path/to/tor`
  - `-DXMRIG=/path/to/xmrig`
- Allow solo mining for XMRig
- Redesign XMRig settings screen
2020-10-18 22:01:14 +02:00
dsc 5d8700370b Merge pull request 'Xmrig: add support for TLS. Tor default off. Save username/password in wallet cache.' (#85) from dsc/feather:xmrig-tab-2 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/85
2020-10-16 20:59:14 +00:00
dsc 1ef29207d5 Xmrig: add support for TLS. Tor default off. Save username/password in wallet cache.
Signed-off-by: dsc <dsc@xmr.pm>
2020-10-16 21:13:14 +02:00
tobtoht 497567e61f Merge pull request 'Bugfix: fix wallet closing issues by partially reverting #63' (#84) from tobtoht/feather:duplicate_wizard into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/84
2020-10-16 15:39:45 +00:00
tobtoht 15c51e2e2b Bugfix: fix wallet closing issues by partially reverting #63 2020-10-16 17:17:31 +02:00
tobtoht c5a055eb70 Merge pull request 'Prices: add support for NZD' (#82) from tobtoht/feather:nzd into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/82
2020-10-16 13:15:12 +00:00
tobtoht 1b9cc7c679 Prices: add support for NZD 2020-10-16 15:14:13 +02:00
tobtoht 0f0b033fe4 Merge pull request 'Fix indefinite hang when closing wallet via File -> Quit' (#80) from tobtoht/feather:close_without_indefinite_hang into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/80
2020-10-16 03:17:54 +00:00
tobtoht 3feda6d6c7 Fix indefinite hang when closing wallet via File -> Quit 2020-10-16 05:15:46 +02:00
dsc 103965ef40 Merge pull request 'Drone: fix AppImage builds' (#77) from dsc/feather:drone_appimage-fix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/77
2020-10-15 23:49:39 +00:00
tobtohtandrm 3ee5e003a7 Drone: fix AppImage builds 2020-10-16 01:49:03 +02:00
dsc 96ac717ede Merge pull request 'XMRig - Simple mining GUI to download/run XMRig' (#76) from dsc/feather:xmrig-tab into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/76
2020-10-15 21:58:25 +00:00
dscandrm d0260ce018 XMRig tab - Simple mining GUI to download and run XMRig releases. 2020-10-15 23:29:15 +02:00
tobtoht 61a135e1c2 Merge pull request 'Send: show fiat conversion when XMR is selected' (#75) from tobtoht/feather:send_fiat into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/75
2020-10-15 02:20:44 +00:00
tobtoht 98db512164 Send: show fiat conversion when XMR is selected 2020-10-15 04:17:57 +02:00
tobtoht a325883b62 Merge pull request 'Tails: fix slow wallet open' (#72) from tobtoht/feather:tails_fix_slow_open into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/72
2020-10-15 01:25:31 +00:00
tobtoht 5c7c13d76a Tails: fix slow wallet open 2020-10-15 02:19:13 +02:00
tobtoht 06cee3f03e Merge pull request 'DebugInfoDialog: Add Tails version' (#69) from tobtoht/feather:tails_version into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/69
2020-10-15 00:00:35 +00:00
tobtoht ec0d88cf1b DebugInfoDialog: Add Tails version 2020-10-15 01:37:42 +02:00
tobtoht eca37f934c Merge pull request 'Fix wallet update regression' (#68) from tobtoht/feather:no_update into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/68
2020-10-14 22:40:56 +00:00
tobtoht 18cf749ad9 Fix wallet update regression
Would cause subaddresses and history to update more often than necessary.
2020-10-15 00:39:30 +02:00
tobtoht 1febbc869f Merge pull request 'Export/Import KeyImages/Outputs' (#66) from tobtoht/feather:keyimages into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/66
2020-10-14 20:13:26 +00:00
tobtoht ea49097ab3 Merge pull request 'Close wallet on exit' (#67) from tobtoht/feather:close_on_exit into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/67
2020-10-14 18:45:22 +00:00
tobtoht 1dcc69db39 Close wallet on exit 2020-10-14 20:44:26 +02:00
tobtoht fc3ac2eb33 Export/Import KeyImages/Outputs 2020-10-14 20:18:25 +02:00
dsc 0289aba113 Merge pull request 'AboutDialog: minor layout fix' (#62) from tobtoht/feather:about_fix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/62
2020-10-14 15:00:55 +00:00
dsc 15f076f7d6 Merge pull request 'Coins: add key image icons for view only wallets' (#59) from tobtoht/feather:coins_no_keyimage into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/59
2020-10-14 14:57:42 +00:00
dsc 63e2ba799d Merge pull request 'Libwalletqt: integrate changes from upstream' (#63) from tobtoht/feather:syncing into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/63
2020-10-14 14:55:10 +00:00
tobtohtandxiphon 1ff8a2aaf4 Libwalletqt: integrate changes from upstream
Co-authored-by: xiphon <xiphon@protonmail.com>
2020-10-14 16:50:38 +02:00
tobtoht 980340546a AboutDialog: minor layout fix 2020-10-14 14:15:03 +02:00
tobtoht ebde5a1cb7 Coins: add key image icons for view only wallets 2020-10-14 04:21:38 +02:00
tobtoht ffa8c3e5bf Merge pull request 'Rebase to Monero Core v0.17.1.0' (#58) from tobtoht/feather:v_17_1_0 into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/58
2020-10-14 01:12:14 +00:00
tobtoht 5a8641660c Rebase to Monero Core v0.17.1.0 2020-10-14 03:04:17 +02:00
dsc 36641d73a6 Merge pull request 'Open/create view-only wallets' (#53) from dsc/feather:view-only into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/53
2020-10-13 19:20:06 +00:00
dsc eac29cd0b6 Import wallet from keys (view-only)
Signed-off-by: dsc <dsc@xmr.pm>
2020-10-13 21:09:33 +02:00
dsc e8a5f59b4c Merge pull request 'Fix segfault on close' (#55) from tobtoht/feather:wizard_segv into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/55
2020-10-13 14:05:33 +00:00
tobtoht 7526714b4a Fix segfault on close
m_wizard has a parent now.
2020-10-13 15:53:33 +02:00
dsc 2ab78022f5 Merge pull request 'Fix misc image scaling hangs' (#54) from tobtoht/feather:img_hang into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/54
2020-10-13 13:53:32 +00:00
tobtoht 363bf0ea38 Fix misc image scaling hangs 2020-10-13 15:45:55 +02:00
dsc d465639d2a Merge pull request 'Fix debug build' (#52) from dsc/feather:fix-rpath-debug into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/52
2020-10-12 15:43:01 +00:00
dsc 0790b30b5d Commit cd1cd5cb75
introduced an issue for CMAKE_BUILD_TYPE=Debug:

  libringct.so => not found
  libcryptonote_basic.so => not found
  libcheckpoints.so => not found
  libdevice.so => not found
  libringct_basic.so => not found
  libcommon.so => not found
  libwallet-crypto.so => not found
  libcncrypto.so => not found
  libeasylogging.so => not found
  librandomx.so => not found
  libversion.so => not found

We'll only set `CMAKE_SKIP_RPATH` when in release.
2020-10-12 17:42:34 +02:00
176 changed files with 7008 additions and 9385 deletions
+24 -27
View File
@@ -14,11 +14,10 @@ steps:
commands: commands:
- git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/ - git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/
- git config --global url."http://gitea:3000/".insteadOf https://github.com/ - git config --global url."http://gitea:3000/".insteadOf https://github.com/
- git submodule update --init --depth 50 contrib/tor - git config --global url."http://gitea:3000/".insteadOf https://git.wownero.com/
- git submodule update --init --depth 50 contrib/torsocks - git submodule update --init monero
- git submodule update --init --depth 120 monero - git submodule update --init --depth 1 --recursive monero
- git submodule update --init --depth 120 --recursive monero - TOR_BIN="/usr/local/tor/bin/tor" make -j8 release-static
- make -j8 release-static
environment: environment:
OPENSSL_ROOT_DIR: /usr/local/openssl/ OPENSSL_ROOT_DIR: /usr/local/openssl/
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
@@ -30,7 +29,7 @@ steps:
- name: files_linux_release - name: files_linux_release
path: /files path: /files
commands: commands:
- export FN="feather-`git rev-parse --short HEAD`.zip" - export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip"
- export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH" - export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH"
- mkdir -p "$TARGET_DIR" - mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
@@ -44,20 +43,22 @@ volumes:
path: /var/drone/ccache_linux_release/ path: /var/drone/ccache_linux_release/
- name: files_linux_release - name: files_linux_release
host: host:
path: /mnt/storage1/feather_files/files/linux-release/ path: /build/feather_files/files/linux-release/
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: linux-release-appimage name: linux-release-appimage
steps: steps:
- name: build - name: build
image: feather:appimage image: feather:appimage
volumes:
- name: files_linux_release
path: /files
commands: commands:
- export FN="feather-`git rev-parse --short HEAD`.zip" - export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip"
- export BRANCH="$DRONE_SOURCE_BRANCH" - export BRANCH="$DRONE_SOURCE_BRANCH"
- cp /files/$BRANCH/$FN feather.zip
- bash ./contrib/build-appimage.sh - bash ./contrib/build-appimage.sh
- name: deploy - name: deploy
image: feather:appimage image: feather:appimage
@@ -71,18 +72,18 @@ steps:
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
- mv "Feather-1.0-x86_64.AppImage" "$TARGET_DIR/$FN" - mv "Feather-1.0-x86_64.AppImage" "$TARGET_DIR/$FN"
- echo "[*] written to https://build.featherwallet.org/files/linux-release-appimage/$DRONE_SOURCE_BRANCH/$FN" - echo "[*] written to https://build.featherwallet.org/files/linux-release-appimage/$DRONE_SOURCE_BRANCH/$FN"
volumes: volumes:
- name: files_linux_appimage - name: files_linux_appimage
host: host:
path: /mnt/storage1/feather_files/files/linux-release-appimage/ path: /build/feather_files/files/linux-release-appimage/
- name: files_linux_release
host:
path: /build/feather_files/files/linux-release/
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: windows-mxe-release name: windows-mxe-release
steps: steps:
- name: build - name: build
image: feather:win image: feather:win
@@ -94,11 +95,10 @@ steps:
commands: commands:
- git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/ - git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/
- git config --global url."http://gitea:3000/".insteadOf https://github.com/ - git config --global url."http://gitea:3000/".insteadOf https://github.com/
- git submodule update --init --depth 50 contrib/tor - git config --global url."http://gitea:3000/".insteadOf https://git.wownero.com/
- git submodule update --init --depth 50 contrib/torsocks - git submodule update --init monero
- git submodule update --init --depth 120 monero - git submodule update --init --depth 1 --recursive monero
- git submodule update --init --depth 120 --recursive monero - PATH="/mxe/usr/bin/:$PATH" TOR_BIN="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" make -j8 windows-mxe-release
- PATH=/mxe/usr/bin/:$PATH make -j8 windows-mxe-release
environment: environment:
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
- name: deploy - name: deploy
@@ -109,23 +109,21 @@ steps:
- name: files_win_release - name: files_win_release
path: /files path: /files
commands: commands:
- export FN="feather-`git rev-parse --short HEAD`.zip" - export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip"
- export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH" - export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH"
- mkdir -p "$TARGET_DIR" - mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
- zip -j "$TARGET_DIR/$FN" build/feather.log build/bin/feather.exe - zip -j "$TARGET_DIR/$FN" build/feather.log build/bin/feather.exe
- echo "[*] written to https://build.featherwallet.org/files/windows-mxe-release/$DRONE_SOURCE_BRANCH/$FN" - echo "[*] written to https://build.featherwallet.org/files/windows-mxe-release/$DRONE_SOURCE_BRANCH/$FN"
volumes: volumes:
- name: ccache_win_release - name: ccache_win_release
host: host:
path: /var/drone/ccache_win_release/ path: /var/drone/ccache_win_release/
- name: files_win_release - name: files_win_release
host: host:
path: /mnt/storage1/feather_files/files/windows-mxe-release/ path: /build/feather_files/files/windows-mxe-release/
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: mac-release name: mac-release
@@ -138,7 +136,6 @@ steps:
path: /files path: /files
commands: commands:
- mkdir -p build - mkdir -p build
- scp -P22 utils/build_macos.sh administrator@steve.jobs.xmr.pm:build_macos.sh
- ssh administrator@steve.jobs.xmr.pm "chmod +x build_macos.sh && PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin ~/build_macos.sh $DRONE_COMMIT_SHA" - ssh administrator@steve.jobs.xmr.pm "chmod +x build_macos.sh && PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin ~/build_macos.sh $DRONE_COMMIT_SHA"
- scp -P22 administrator@steve.jobs.xmr.pm:feather.zip build/feather.zip - scp -P22 administrator@steve.jobs.xmr.pm:feather.zip build/feather.zip
- name: deploy - name: deploy
@@ -147,7 +144,7 @@ steps:
- name: files_mac_release - name: files_mac_release
path: /files path: /files
commands: commands:
- export FN="feather-`git rev-parse --short HEAD`.zip" - export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip"
- export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH" - export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH"
- mkdir -p "$TARGET_DIR" - mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
@@ -157,9 +154,9 @@ steps:
volumes: volumes:
- name: files_mac_release - name: files_mac_release
host: host:
path: /mnt/storage1/feather_files/files/mac-release/ path: /build/feather_files/files/mac-release/
--- ---
kind: signature kind: signature
hmac: 91e773a27d27f29ea62f5df500664b733df641b7c31202c8e5558174fd046fba hmac: f16a0379280e2e89987930d635ec6fb938d67732fdaf4ddc488f2a9db64bda2c
... ...
+3 -3
View File
@@ -1,9 +1,9 @@
[submodule "monero"] [submodule "monero"]
path = monero path = monero
url = https://git.wownero.com/feather/monero.git url = https://git.wownero.com/feather/monero.git
[submodule "contrib/torsocks"]
path = contrib/torsocks
url = https://git.torproject.org/torsocks.git
[submodule "contrib/tor"] [submodule "contrib/tor"]
path = contrib/tor path = contrib/tor
url = https://git.torproject.org/tor.git url = https://git.torproject.org/tor.git
[submodule "contrib/KDMacTouchBar"]
path = contrib/KDMacTouchBar
url = https://github.com/KDAB/KDMacTouchBar.git
+40 -35
View File
@@ -10,6 +10,44 @@ Static builds via Docker are done in 3 steps:
2. Creating a base Docker image 2. Creating a base Docker image
3. Using the base image to compile a build 3. Using the base image to compile a build
### Linux (reproducible)
The docker image for reproducible Linux static builds uses Ubuntu 16.04 and compiles the required libraries statically
so that the resulting Feather binary is static. For more information, check the Dockerfile: `Dockerfile`.
#### 1. Clone
```bash
git clone --branch master --recursive https://git.wownero.com/feather/feather.git
cd feather
```
Replace `master` with the desired version tag (e.g. `beta-1`) to build the release binary.
#### 2. Base image
```bash
docker build --tag feather:linux --build-arg THREADS=4 .
```
Building the base image takes a while. You only need to build the base image once.
#### 3. Build
```bash
docker run --rm -it -v $PWD:/feather --env OPENSSL_ROOT_DIR=/usr/local/openssl/ -w /feather feather:linux sh -c 'TOR_BIN="/usr/local/tor/bin/tor" make release-static -j4'
```
If you're re-running a build make sure to `rm -rf build/` first.
The resulting binary can be found in `build/bin/feather`.
Hashes for tagged commits should match:
```
beta-1: d1a52e3bac1abbae4adda1fc88cb2a7a06fbd61085868421897c6a4f3f4eb091 feather
```
### Windows ### Windows
The docker image for Windows static compiles uses Ubuntu 18.04 and installs [mxe](https://mxe.cc) from [our git](https://git.wownero.com/feather/mxe/src/branch/feather-patch), The docker image for Windows static compiles uses Ubuntu 18.04 and installs [mxe](https://mxe.cc) from [our git](https://git.wownero.com/feather/mxe/src/branch/feather-patch),
@@ -35,46 +73,13 @@ Note: You only need to build the base image once.
#### 3. Build #### 3. Build
```bash ```bash
docker run --rm -it -v /tmp/ccache:/root/.ccache -v /root/feather:/feather -w /feather feather:win /bin/bash -c 'PATH=/mxe/usr/bin/:$PATH make windows-mxe-release -j8' docker run --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:win /bin/bash -c 'PATH="/mxe/usr/bin/:$PATH" TOR_BIN="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" make windows-mxe-release -j8'
``` ```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally. Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
The resulting binary can be found in `build/bin/feather.exe`. The resulting binary can be found in `build/bin/feather.exe`.
### Linux
The docker image for Linux static compiles uses Ubuntu 18.04 and compiles the required libraries statically so that
the resulting Feather binary is static. It comes with OpenSSL 1.1.1g, Qt 5.15.0 (OpenGL disabled). For more information,
check the Dockerfile: `Dockerfile`.
#### 1. Clone
```bash
git clone --recursive https://git.wownero.com/feather/feather.git
cd feather
```
#### 2. Base image
Warning: Building the base image takes a while, go prepare some dinner.
```bash
docker build --tag feather:linux --build-arg THREADS=8 .
```
Note: You only need to build the base image once.
#### 3. Build
```bash
docker run --env OPENSSL_ROOT_DIR=/usr/local/openssl/ --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:linux sh -c 'make release-static -j8'
```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
The resulting binary can be found in `build/bin/feather`.
## macOS ## macOS
For MacOS it's easiest to leverage [brew](https://brew.sh) to install the required dependencies. For MacOS it's easiest to leverage [brew](https://brew.sh) to install the required dependencies.
@@ -98,4 +103,4 @@ Build Feather.
CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release
``` ```
The resulting Mac OS application can be found `build/bin/feather.app`. The resulting Mac OS application can be found `build/bin/feather.app` and will **not** have Tor embedded.
+35 -41
View File
@@ -7,11 +7,14 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
set(VERSION_MAJOR "0") set(VERSION_MAJOR "0")
set(VERSION_MINOR "1") set(VERSION_MINOR "1")
set(VERSION_REVISION "0") set(VERSION_REVISION "0")
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}") set(VERSION "beta-2")
option(FETCH_DEPS "Download dependencies if they are not found" ON) option(FETCH_DEPS "Download dependencies if they are not found" ON)
option(XMRTO "Include Xmr.To module" ON) option(XMRTO "Include Xmr.To module" ON)
option(BUILD_TOR "Build Tor" OFF) option(MORPHTOKEN "Include MorphToken module" ON)
option(XMRIG "Include XMRig module" ON)
option(TOR_BIN "Path to Tor binary to embed inside Feather" OFF)
option(STATIC "Link libraries statically, requires static Qt") option(STATIC "Link libraries statically, requires static Qt")
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF) option(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
option(DONATE_BEG "Prompt donation window every once in a while" ON) option(DONATE_BEG "Prompt donation window every once in a while" ON)
@@ -28,7 +31,7 @@ if(DEBUG)
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
endif() endif()
set(MONERO_HEAD "a1404e92cb439ba0f120e7c4a579ed0b9a0372a4") set(MONERO_HEAD "85b0b4f73aa6114e3ff91207aa94ad2a15c939a2")
set(BUILD_GUI_DEPS ON) set(BUILD_GUI_DEPS ON)
set(ARCH "x86-64") set(ARCH "x86-64")
set(BUILD_64 ON) set(BUILD_64 ON)
@@ -157,7 +160,11 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
locale) locale)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
# https://github.com/monero-project/monero-gui/issues/3142#issuecomment-705940446
set(CMAKE_SKIP_RPATH ON) set(CMAKE_SKIP_RPATH ON)
endif()
find_package(X11 REQUIRED) find_package(X11 REQUIRED)
message(STATUS "X11_FOUND = ${X11_FOUND}") message(STATUS "X11_FOUND = ${X11_FOUND}")
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}") message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
@@ -170,47 +177,30 @@ if(UNIX AND NOT APPLE)
endif() endif()
endif() endif()
# Tor/torsocks if("$ENV{DRONE}" STREQUAL "true")
set(TOR_TAG "tor-0.4.3.5")
set(TOR_DIR "${CMAKE_SOURCE_DIR}/contrib/tor")
if(BUILD_TOR AND APPLE)
execute_process(COMMAND bash -c "touch ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
ENDIF()
if(UNIX AND NOT APPLE)
set(TOR_LIB "libtorsocks.so")
elseif(APPLE)
set(TOR_LIB "libtorsocks.dylib")
endif()
if("$ENV{DRONE}" STREQUAL "true" AND APPLE)
message(STATUS "We are inside a static compile with Drone CI") message(STATUS "We are inside a static compile with Drone CI")
# @TODO: taken from Tor Browser official release for now
execute_process(COMMAND bash -c "cp ~/tor/libevent-2.1.7.dylib ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
execute_process(COMMAND bash -c "cp ~/tor/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
elseif("$ENV{DRONE}" STREQUAL "true" AND BUILD_TOR)
message(STATUS "We are inside a static compile with Drone CI")
if(MINGW)
execute_process(COMMAND bash -c "cp /mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe ${CMAKE_SOURCE_DIR}/src/tor/tor.exe")
elseif(UNIX AND NOT APPLE)
execute_process(COMMAND bash -c "cp /usr/local/tor/bin/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
execute_process(COMMAND bash -c "cp /usr/local/torsocks/lib/torsocks/* ${CMAKE_SOURCE_DIR}/src/tor/")
endif() endif()
# To build Feather with embedded (and static) Tor, pass CMake -DTOR_BIN=/path/to/tor
if(TOR_BIN)
if(APPLE)
execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
endif()
# on the buildbot Tor is baked into the image
# - linux: See `Dockerfile`
# - windows: https://github.com/mxe/mxe/blob/1024dc7d2db5eb7d5d3c64a2c12b5f592572f1ce/plugins/apps/tor.mk
# - macos: taken from Tor Browser official release
set(TOR_COPY_CMD "cp ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
message(STATUS "${TOR_COPY_CMD}")
execute_process(COMMAND bash -c "${TOR_COPY_CMD}" RESULT_VARIABLE ret)
if(ret EQUAL "1")
message(FATAL_ERROR "Tor copy failure: ${TOR_COPY_CMD}")
endif()
message(STATUS "Embedding Tor binary at ${TOR_BIN}")
else() else()
if(BUILD_TOR) message(STATUS "Skipping Tor inclusion because -DTOR_BIN=Off")
if(UNIX OR APPLE)
execute_process(COMMAND bash -c "ls -al src/tor/${TOR_LIB} 2>/dev/null" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE TOR_FOUND OUTPUT_STRIP_TRAILING_WHITESPACE)
if(TOR_FOUND)
message(STATUS "${TOR_LIB} found, skipping Tor build")
else()
message(STATUS "${TOR_LIB} not found, building Tor")
execute_process(COMMAND bash -c "bash build_tor.sh ${TOR_TAG} ${CMAKE_SOURCE_DIR} 'ON'" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/contrib)
endif()
endif()
else()
message(STATUS "Skipping Tor build because -DBUILD_TOR=OFF")
endif()
endif() endif()
if(MINGW) if(MINGW)
@@ -358,4 +348,8 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${C_SECURITY_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}")
if(APPLE)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/contrib/KDMacTouchBar")
endif()
add_subdirectory(src) add_subdirectory(src)
+174 -133
View File
@@ -1,188 +1,214 @@
FROM ubuntu:18.04 FROM ubuntu:16.04
ARG THREADS=1 ARG THREADS=1
ARG QT_VERSION=5.15.2
RUN apt clean && apt update ENV CFLAGS="-fPIC"
RUN apt install -y gnupg ENV CPPFLAGS="-fPIC"
ENV CXXFLAGS="-fPIC"
ENV SOURCE_DATE_EPOCH=1397818193
COPY utils/pubkeys/kitware.asc /kitware.asc RUN apt-get update
RUN cat /kitware.asc | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null RUN apt-get install -y nano vim ccache software-properties-common
RUN apt install -y automake git pkg-config python wget python3.6-distutils software-properties-common
RUN apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' && apt update
ARG DEBIAN_FRONTEND=noninteractive RUN add-apt-repository ppa:git-core/ppa
ENV TZ=Europe/Amsterdam RUN apt-get update
RUN apt install -y build-essential nano vim aptitude ccache libusb-1.0-0-dev tzdata
RUN apt install -y xutils-dev && \ RUN apt install -y automake git pkg-config python xutils-dev && \
git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \ git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
cd xorgproto && \ cd xorgproto && \
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \ git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ ./autogen.sh && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b xcb-proto-1.13 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbproto && \ RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbproto && \
cd xcbproto && \ cd xcbproto && \
git reset --hard 94228cde97d9aecfda04a8e699d462ba2b89e3a0 && \ git reset --hard 6398e42131eedddde0d98759067dde933191f049 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ ./autogen.sh && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libtool-bin && \ RUN apt install -y libtool-bin && \
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \ git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
cd libxau && \ cd libxau && \
git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \ git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ ./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libpthread-stubs0-dev && \ RUN apt install -y libpthread-stubs0-dev && \
git clone -b 1.13.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \ git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
cd libxcb && \ cd libxcb && \
git reset --hard 8287ebd7b752c33b0cabc4982606fe4831106f7e && \ git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ ./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
make -j$THREADS clean && \
rm /usr/local/lib/libxcb-xinerama.so && \
./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
cp src/.libs/libxcb-xinerama.a /usr/local/lib/ && \
rm -rf $(pwd)
RUN git clone -b 0.4.0 --depth 1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-util.git && \ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-util && \
cd libxcb-util && \ cd libxcb-util && \
git reset --hard acf790d7752f36e450d476ad79807d4012ec863b && \ git reset --hard acf790d7752f36e450d476ad79807d4012ec863b && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b xtrans-1.3.5 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxtrans.git && \ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-image && \
cd libxtrans && \
git reset --hard 7cbad9fe2e61cd9d5caeaf361826a6f4bd320f03 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install
RUN git clone -b 0.4.0 --depth 1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-image.git && \
cd libxcb-image && \ cd libxcb-image && \
git reset --hard d882052fb2ce439c6483fce944ba8f16f7294639 && \ git reset --hard d882052fb2ce439c6483fce944ba8f16f7294639 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.4.0 --depth 1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms.git && \ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms && \
cd libxcb-keysyms && \ cd libxcb-keysyms && \
git reset --hard 0e51ee5570a6a80bdf98770b975dfe8a57f4eeb1 && \ git reset --hard 0e51ee5570a6a80bdf98770b975dfe8a57f4eeb1 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.3.9 --depth 1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-render-util.git && \ RUN git clone -b 0.3.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-render-util && \
cd libxcb-render-util && \ cd libxcb-render-util && \
git reset --hard 0317caf63de532fd7a0493ed6afa871a67253747 && \ git reset --hard 0317caf63de532fd7a0493ed6afa871a67253747 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.4.1 --depth 1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-wm.git && \ RUN git clone -b 0.4.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-wm && \
cd libxcb-wm && \ cd libxcb-wm && \
git reset --hard 24eb17df2e1245885e72c9d4bbb0a0f69f0700f2 && \ git reset --hard 24eb17df2e1245885e72c9d4bbb0a0f69f0700f2 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libX11-1.6.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libx11 && \ RUN apt install -y bison && \
cd libx11 && \ git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbcommon && \
git reset --hard db7cca17ad7807e92a928da9d4c68a00f4836da2 && \ cd libxkbcommon && \
ACLOCAL='aclocal -I /usr/local/share/aclocal/' CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ git reset --hard c43c3c866eb9d52cd8f61e75cbef1c30d07f3a28 && \
./autogen.sh --prefix=/usr --enable-shared --disable-static --enable-x11 --disable-docs && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libXext-1.3.4 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxext && \
cd libxext && \
git reset --hard ebb167f34a3514783966775fb12573c4ed209625 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install
RUN apt install -y libpthread-stubs0-dev && \
git clone -b libXinerama-1.1.4 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxinerama.git && \
cd libxinerama && \
git reset --hard c3ab2361f13154921df2992f9eacc1ea1b3f946b && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \ RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
cd zlib && \ cd zlib && \
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \ git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --static && \ ./configure --static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install && \ make -j$THREADS install && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --static --prefix=/usr/local/zlib && \ ./configure --static --prefix=/usr/local/zlib && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b VER-2-10-2 https://git.sv.nongnu.org/r/freetype/freetype2.git && \ RUN git clone -b VER-2-10-2 --depth 1 https://git.savannah.gnu.org/git/freetype/freetype2.git && \
cd freetype2 && \ cd freetype2 && \
git reset --hard 132f19b779828b194b3fede187cee719785db4d8 && \ git reset --hard 132f19b779828b194b3fede187cee719785db4d8 && \
./autogen.sh && \ ./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --with-zlib=no && \ ./configure --disable-shared --enable-static --with-zlib=no && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \ RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
cd libexpat/expat && \ cd libexpat/expat && \
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \ git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
./buildconf.sh && \ ./buildconf.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \ ./configure --disable-shared --enable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y autopoint gettext gperf libpng-dev && \ RUN apt install -y autopoint gettext gperf libpng12-dev && \
git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \ git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
cd fontconfig && \ cd fontconfig && \
git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \ git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \ ./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \ RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
cd icu/icu4c/source && \ cd icu/icu4c/source && \
git reset --hard e2d85306162d3a0691b070b4f0a73e4012433444 && \ git reset --hard e2d85306162d3a0691b070b4f0a73e4012433444 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-tests --disable-samples && \ ./configure --disable-shared --enable-static --disable-tests --disable-samples && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y wget && \ RUN apt install -y wget && \
wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \ wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" > hashsum.txt && \ echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
sha256sum -c hashsum.txt && \ tar -xzf boost_1_73_0.tar.gz && \
tar -xvzf boost_1_73_0.tar.gz && \ rm boost_1_73_0.tar.gz && \
cd boost_1_73_0 && \ cd boost_1_73_0 && \
./bootstrap.sh && \ ./bootstrap.sh && \
./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags='-fPIC' cxxflags='-fPIC' install -a --prefix=/usr ./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags="${CFLAGS}" cxxflags="${CXXFLAGS}" install -a --prefix=/usr && \
rm -rf $(pwd)
RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \ RUN wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" > hashsum.txt && \ echo "e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242 openssl-1.1.1i.tar.gz" | sha256sum -c && \
sha256sum -c hashsum.txt && \ tar -xzf openssl-1.1.1i.tar.gz && \
tar -xzf openssl-1.1.1g.tar.gz && \ rm openssl-1.1.1i.tar.gz && \
cd openssl-1.1.1g && \ cd openssl-1.1.1i && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./config no-shared no-zlib-dynamic --prefix=/usr/local/openssl && \ ./config no-shared no-zlib-dynamic --prefix=/usr/local/openssl && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
./config no-shared no-zlib-dynamic --openssldir=/usr && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN wget https://download.qt.io/archive/qt/5.15/5.15.0/single/qt-everywhere-src-5.15.0.tar.xz && \ RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
echo "22b63d7a7a45183865cc4141124f12b673e7a17b1fe2b91e433f6547c5d548c3 qt-everywhere-src-5.15.0.tar.xz" > hashsum.txt && \ rm /usr/lib/x86_64-linux-gnu/libX11.a && \
sha256sum -c hashsum.txt && \ rm /usr/lib/x86_64-linux-gnu/libXext.a && \
tar -xf qt-everywhere-src-5.15.0.tar.xz rm /usr/lib/x86_64-linux-gnu/libX11-xcb.a && \
git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
COPY contrib/Qt5.15_LinuxPatch.json /qt-everywhere-src-5.15.0/qtbase/src/gui/configure.json cd qt5 && \
RUN apt install -y libgl1-mesa-dev libglib2.0-dev libxkbcommon-dev libxkbcommon-x11-dev git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
RUN cd /qt-everywhere-src-5.15.0 && \ git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtx11extras.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtwebsockets.git -b ${QT_VERSION} --depth 1 && \
sed -ri s/\(Libs:.*\)/\\1\ -lexpat/ /usr/local/lib/pkgconfig/fontconfig.pc && \ sed -ri s/\(Libs:.*\)/\\1\ -lexpat/ /usr/local/lib/pkgconfig/fontconfig.pc && \
sed -ri s/\(Libs:.*\)/\\1\ -lz/ /usr/local/lib/pkgconfig/freetype2.pc && \ sed -ri s/\(Libs:.*\)/\\1\ -lz/ /usr/local/lib/pkgconfig/freetype2.pc && \
sed -ri s/\(Libs:.*\)/\\1\ -lXau/ /usr/local/lib/pkgconfig/xcb.pc && \ sed -ri s/\(Libs:.*\)/\\1\ -lXau/ /usr/local/lib/pkgconfig/xcb.pc && \
sed -i s/\\/usr\\/X11R6\\/lib64/\\/usr\\/local\\/lib/ qtbase/mkspecs/linux-g++-64/qmake.conf && \
OPENSSL_LIBS="-lssl -lcrypto -lpthread -ldl" \ OPENSSL_LIBS="-lssl -lcrypto -lpthread -ldl" \
./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \ ./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \
-no-opengl -qpa xcb -openssl-linked -I /usr/local/openssl/include -L /usr/local/openssl/lib -system-freetype -fontconfig -glib \ -no-opengl -qpa xcb --xcb -xcb-xlib -feature-xlib -openssl-linked -I /usr/local/openssl/include \
-L /usr/local/openssl/lib -system-freetype -fontconfig -glib \
-no-dbus -no-sql-sqlite -no-use-gold-linker -no-kms \ -no-dbus -no-sql-sqlite -no-use-gold-linker -no-kms \
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \ -qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \ -skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \
@@ -191,84 +217,103 @@ RUN cd /qt-everywhere-src-5.15.0 && \
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \ -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \
-skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \ -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \
-skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine \ -skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine \
-skip qtdeclarative -skip qtmultimedia \ -skip qtdeclarative \
-no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation \ -no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation \
-nomake examples -nomake tests -nomake tools -nomake examples -nomake tests -nomake tools && \
RUN cd /qt-everywhere-src-5.15.0 && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
cd qttools/src/linguist/lrelease && \
RUN cd qt-everywhere-src-5.15.0/qttools/src/linguist/lrelease && \ ../../../../qtbase/bin/qmake && \
qmake && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
cd ../../../.. && \
rm -rf $(pwd)
RUN apt install -y libudev-dev && \ RUN apt install -y libudev-dev && \
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \ git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
cd libusb && \ cd libusb && \
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \ git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \ ./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \ RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
cd hidapi && \ cd hidapi && \
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \ git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
./bootstrap && \ ./bootstrap && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \ ./configure --disable-shared --enable-static && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libsodium-dev && \ RUN apt install -y libsodium-dev && \
git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \ git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \
cd libzmq && \ cd libzmq && \
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \ git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
./autogen.sh && \ ./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-libunwind --with-libsodium && \ ./configure --disable-shared --enable-static --disable-libunwind --with-libsodium && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git && \ RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git && \
cd libgpg-error && \ cd libgpg-error && \
git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \ git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \
./autogen.sh && \ ./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-doc --disable-tests && \ ./configure --disable-shared --enable-static --disable-doc --disable-tests && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git && \ RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git && \
cd libgcrypt && \ cd libgcrypt && \
git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \ git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \
./autogen.sh && \ ./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-doc && \ ./configure --disable-shared --enable-static --disable-doc && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b v3.10.0 --depth 1 https://github.com/protocolbuffers/protobuf && \ RUN git clone -b v3.10.0 --depth 1 https://github.com/protocolbuffers/protobuf && \
cd protobuf && \ cd protobuf && \
git reset --hard 6d4e7fd7966c989e38024a8ea693db83758944f1 && \ git reset --hard 6d4e7fd7966c989e38024a8ea693db83758944f1 && \
./autogen.sh && \ ./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --enable-static --disable-shared && \ ./configure --enable-static --disable-shared && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y zip cmake && git clone -b v4.0.2 --depth 1 https://github.com/fukuchi/libqrencode.git && \ RUN git clone -b v3.18.4 --depth 1 https://github.com/Kitware/CMake && \
cd CMake && \
git reset --hard 3cc3d42aba879fff5e85b363ae8f21386a3f9f9b && \
./bootstrap && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libusb-1.0-0-dev
RUN apt install -y zip && git clone -b v4.0.2 --depth 1 https://github.com/fukuchi/libqrencode.git && \
cd libqrencode && \ cd libqrencode && \
git reset --hard 59ee597f913fcfda7a010a6e106fbee2595f68e4 && \ git reset --hard 59ee597f913fcfda7a010a6e106fbee2595f68e4 && \
cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr . && \ cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr . && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libmbedtls-dev && git clone -b release-2.1.12-stable --depth 1 https://github.com/libevent/libevent.git && \ RUN apt install -y libmbedtls-dev && git clone -b release-2.1.12-stable --depth 1 https://github.com/libevent/libevent.git && \
cd libevent && \ cd libevent && \
git reset --hard 5df3037d10556bfcb675bc73e516978b75fc7bc7 && \
mkdir build && cd build && \ mkdir build && cd build && \
cmake -DEVENT_LIBRARY_STATIC=ON -DOPENSSL_ROOT_DIR=/usr/local/openssl -DCMAKE_INSTALL_PREFIX=/usr/local/libevent .. && \ cmake -DEVENT_LIBRARY_STATIC=ON -DOPENSSL_ROOT_DIR=/usr/local/openssl -DCMAKE_INSTALL_PREFIX=/usr/local/libevent .. && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b tor-0.4.3.5 --depth 1 https://git.torproject.org/tor.git && \ RUN git clone -b tor-0.4.4.6 --depth 1 https://git.torproject.org/tor.git && \
cd tor && \ cd tor && \
git reset --hard 2a8b789ea6f308d081f369d78fa7cfdc9d00bf90 && \
bash autogen.sh && \ bash autogen.sh && \
LDFLAGS="-L/usr/local/openssl/lib/" LIBS="-lssl -lcrypto -lpthread -ldl" CPPFLAGS="-I/usr/local/openssl/include/" ./configure \ LDFLAGS="-L/usr/local/openssl/lib/" LIBS="-lssl -lcrypto -lpthread -ldl" CPPFLAGS="-I/usr/local/openssl/include/" ./configure \
--enable-static-zlib \ --enable-static-zlib \
@@ -291,17 +336,13 @@ RUN git clone -b tor-0.4.3.5 --depth 1 https://git.torproject.org/tor.git && \
--disable-system-torrc \ --disable-system-torrc \
--prefix=/usr/local/tor && \ --prefix=/usr/local/tor && \
make -j$THREADS && \ make -j$THREADS && \
make -j$THREADS install make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone https://git.torproject.org/torsocks.git && \
cd torsocks && \
bash autogen.sh && \
./configure --prefix=/usr/local/torsocks && \
make -j$THREADS && \
make -j$THREADS install
RUN git clone https://git.wownero.com/feather/monero-seed.git && \ RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cd monero-seed && \ cd monero-seed && \
git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \ make -Cbuild -j$THREADS && \
make -Cbuild install make -Cbuild install && \
rm -rf $(pwd)
+1 -1
View File
@@ -3,7 +3,7 @@ FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt clean && apt update RUN apt clean && apt update
RUN apt install -y golang git build-essential wget curl ngrep unzip file squashfs-tools desktop-file-utils patchelf libxkbcommon-x11-dev RUN apt install -y golang git build-essential wget curl ngrep unzip file squashfs-tools desktop-file-utils patchelf libxkbcommon-x11-dev libx11-xcb-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render0 libxcb-render-util0 libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-shm0 libxcb-keysyms1 libxcb-xkb1
RUN go get github.com/probonopd/go-appimage/src/appimagetool RUN go get github.com/probonopd/go-appimage/src/appimagetool
RUN go build -trimpath -ldflags="-s -w" github.com/probonopd/go-appimage/src/appimagetool RUN go build -trimpath -ldflags="-s -w" github.com/probonopd/go-appimage/src/appimagetool
+1 -1
View File
@@ -50,7 +50,7 @@ RUN apt install -y \
RUN git clone -b feather-patch --depth 1 https://git.wownero.com/feather/mxe.git && \ RUN git clone -b feather-patch --depth 1 https://git.wownero.com/feather/mxe.git && \
cd mxe && \ cd mxe && \
make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats qtmultimedia
# plugins # plugins
RUN cd mxe && make -j$THREADS MXE_PLUGIN_DIRS='/mxe/plugins/apps/' MXE_TARGETS='x86_64-w64-mingw32.static' tor RUN cd mxe && make -j$THREADS MXE_PLUGIN_DIRS='/mxe/plugins/apps/' MXE_TARGETS='x86_64-w64-mingw32.static' tor
+3 -1
View File
@@ -42,7 +42,9 @@ via the `CMAKE_PREFIX_PATH` definition. For me this is:
There are some Monero/Feather related options/definitions that you may pass: There are some Monero/Feather related options/definitions that you may pass:
- `-DXMRTO=OFF` - disable Xmr.To feature - `-DXMRTO=OFF` - disable Xmr.To feature
- `-DBUILD_TOR=OFF` - disable embedded Tor - `-DMORPHTOKEN=OFF` - disable MorphToken feature
- `-DXMRIG=OFF` - disable XMRig feature
- `-DTOR_BIN=/path/to/tor` - Embed a Tor executable inside Feather
- `-DDONATE_BEG=OFF` - disable the dreaded donate requests - `-DDONATE_BEG=OFF` - disable the dreaded donate requests
And: And:
+8 -5
View File
@@ -30,7 +30,10 @@ CMAKEFLAGS = \
-DARCH=x86_64 \ -DARCH=x86_64 \
-DBUILD_64=On \ -DBUILD_64=On \
-DBUILD_TESTS=Off \ -DBUILD_TESTS=Off \
-DXMRTO=ON \ -DXMRTO=On \
-DMORPHTOKEN=On \
-DXMRIG=On \
-DTOR_BIN=Off \
-DCMAKE_CXX_STANDARD=11 \ -DCMAKE_CXX_STANDARD=11 \
-DCMAKE_VERBOSE_MAKEFILE=On \ -DCMAKE_VERBOSE_MAKEFILE=On \
-DINSTALL_VENDORED_LIBUNBOUND=Off \ -DINSTALL_VENDORED_LIBUNBOUND=Off \
@@ -40,29 +43,29 @@ CMAKEFLAGS = \
$(CMAKEFLAGS_EXTRA) $(CMAKEFLAGS_EXTRA)
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64" release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
release-static: CMAKEFLAGS += -DBUILD_TOR=On release-static: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
release-static: release-static:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-release: CMAKEFLAGS += -DBUILD_TOR=On windows-mxe-release: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
windows-mxe-release: windows-mxe-release:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TOR=Off windows-mxe-debug: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug
windows-mxe-debug: windows-mxe-debug:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
mac-release: CMAKEFLAGS += -DSTATIC=Off mac-release: CMAKEFLAGS += -DSTATIC=Off
mac-release: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64" mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64"
mac-release: CMAKEFLAGS += -DBUILD_TOR=Off
mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
mac-release: mac-release:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
+12 -11
View File
@@ -1,34 +1,35 @@
# Maintainer: wowario <wowario[at]protonmail[dot]com> # Maintainer: wowario <wowario[at]protonmail[dot]com>
# Contributor: wowario <wowario[at]protonmail[dot]com> # Contributor: wowario <wowario[at]protonmail[dot]com>
pkgbase=('monero-feather-git') pkgname='monero-feather-git'
pkgname=('monero-feather-git') pkgver=0.1.0.925ef5683
pkgver=v0.1.0.0.cd1cd5cb75
pkgrel=1 pkgrel=1
pkgdesc="a free Monero desktop wallet" pkgdesc='a free Monero desktop wallet'
license=('BSD') license=('BSD')
arch=('x86_64') arch=('x86_64')
url="https://featherwallet.org" url="https://featherwallet.org"
depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'zeromq' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc' depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc' 'libgcrypt' 'qrencode' 'libsodium' 'libpgm' 'expat' 'qt5-base' 'qt5-websockets' 'tor')
'libgcrypt' 'qrencode' 'ccache' 'libsodium' 'libpgm' 'expat' 'base-devel' 'qt5-base')
makedepends=('git' 'cmake' 'boost') makedepends=('git' 'cmake' 'boost')
provides=('monero-feather-git')
source=("${pkgname}"::"git+https://git.wownero.com/feather/feather") source=("${pkgname}"::"git+https://git.wownero.com/feather/feather")
sha256sums=('SKIP') sha256sums=('SKIP')
pkgver() { pkgver() {
cd "$srcdir/$pkgname" cd "${srcdir}/${pkgname}"
git describe --long --tags | sed 's/\([^-]*-\)g/r\1/;s/-/./g' printf "%s.%s" "$(git describe --tags --abbrev=0)" "$(git rev-parse --short=9 HEAD)"
} }
build() { build() {
cd "${srcdir}/${pkgname}" cd "${srcdir}/${pkgname}"
mkdir build && cd build && cmake .. && make release-static -j2 git submodule update --init --recursive
mkdir -p build
cd build
cmake ..
make
} }
package_feather-git() { package_monero-feather-git() {
install -Dm644 "${srcdir}/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" install -Dm644 "${srcdir}/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
install -Dm755 "${srcdir}/${pkgname}/build/bin/feather" "${pkgdir}/usr/bin/feather" install -Dm755 "${srcdir}/${pkgname}/build/bin/feather" "${pkgdir}/usr/bin/feather"
} }
-22
View File
@@ -2,33 +2,11 @@
set -e set -e
function verify_hash() {
local file=$1 expected_hash=$2
actual_hash=$(sha256sum $file | awk '{print $1}')
if [ "$actual_hash" == "$expected_hash" ]; then
return 0
else
echo "$file $actual_hash (unexpected hash)" >&2
rm "$file"
exit 1
fi
}
function download_if_not_exist() {
local file_name=$1 url=$2
if [ ! -e $file_name ] ; then
wget -q -O $file_name "$url"
fi
}
APPDIR="$PWD/feather.AppDir" APPDIR="$PWD/feather.AppDir"
mkdir -p "$APPDIR" mkdir -p "$APPDIR"
mkdir -p "$APPDIR/usr/share/applications/" mkdir -p "$APPDIR/usr/share/applications/"
mkdir -p "$APPDIR/usr/bin" mkdir -p "$APPDIR/usr/bin"
echo "Downloading dependencies"
download_if_not_exist "feather.zip" "https://build.featherwallet.org/files/linux-release/$BRANCH/$FN"
unzip -q feather.zip unzip -q feather.zip
cp "$PWD/src/assets/feather.desktop" "$APPDIR/usr/share/applications/feather.desktop" cp "$PWD/src/assets/feather.desktop" "$APPDIR/usr/share/applications/feather.desktop"
-126
View File
@@ -1,126 +0,0 @@
#!/usr/bin/env bash
# this file is used by feather's CMake
# arguments: ./build.tor $TAG $ROOT_FEATHER_DIR
set -ex
ERR_WIN="This script does not work on Windows"
if [[ "$OSTYPE" == "msys" ]]; then
echo "$ERR_WIN"
exit 1
elif [[ "$OSTYPE" == "win32" ]]; then
echo "$ERR_WIN"
exit 1
fi
TOR_TAG="$1"
ROOT_DIR="$2"
STATIC="$3"
TOR_DIR="$ROOT_DIR/contrib/tor"
TORSOCKS_DIR="$ROOT_DIR/contrib/torsocks"
TARGET_DIR="$ROOT_DIR/src/tor"
CPU_CORE_COUNT="$(nproc)"
#
### tor
#
pushd "$TOR_DIR"
rm -rf "$TOR_DIR/build"
mkdir -p "$TOR_DIR/build"
# configure
git -C "$TOR_DIR" fetch
git -C "$TOR_DIR" checkout tor-0.4.3.5
bash "$TOR_DIR/autogen.sh"
if [[ "$STATIC" = "ON" ]]; then
# static assumes that openssl has been compiled with:
# CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./config no-asm no-shared no-zlib-dynamic --prefix=/usr/local/openssl --openssldir=/usr/local/openssl
# and libevent with:
# cmake -DEVENT_LIBRARY_STATIC=ON -DOPENSSL_ROOT_DIR=/usr/local/openssl -DCMAKE_INSTALL_PREFIX=/usr/local/libevent
# and zlib with:
# CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --static --prefix=/usr/local/zlib
LDFLAGS="-L/usr/local/openssl/lib/" LIBS="-lssl -lcrypto -lpthread -ldl" CPPFLAGS="-I/usr/local/openssl/include/" ./configure \
--enable-static-zlib \
--enable-static-openssl \
--enable-static-libevent \
--disable-system-torrc \
--with-libevent-dir=/usr/local/libevent \
--with-openssl-dir=/usr/local/openssl/ \
--with-zlib-dir=/usr/local/zlib \
--disable-system-torrc \
--disable-tool-name-check \
--disable-systemd \
--disable-lzma \
--disable-unittests \
--disable-zstd \
--disable-seccomp \
--disable-asciidoc \
--disable-manpage \
--disable-html-manual \
--disable-system-torrc \
--prefix="$TOR_DIR/build"
else
bash "$TOR_DIR/configure" \
--disable-tool-name-check \
--disable-systemd \
--disable-lzma \
--disable-unittests \
--disable-zstd \
--disable-asciidoc \
--disable-manpage \
--disable-html-manual \
--prefix="$TOR_DIR/build"
fi
# build
make -j "$CPU_CORE_COUNT"
make install -j "$CPU_CORE_COUNT"
# copy to lib/tor
cp "$TOR_DIR/build/bin/tor" "$TARGET_DIR"
cp "$TOR_DIR/build/etc/tor/torrc.sample"* "$TARGET_DIR"
#
### torsocks
#
pushd "$TORSOCKS_DIR"
mkdir -p "$TORSOCKS_DIR/build"
# configure
bash "$TORSOCKS_DIR/autogen.sh"
bash "$TORSOCKS_DIR/configure" --prefix="$TORSOCKS_DIR/build"
# build
make -j "$CPU_CORE_COUNT"
make install -j "$CPU_CORE_COUNT"
# copy to lib/torsocks
cp "$TORSOCKS_DIR/build/lib/torsocks/"* "$TARGET_DIR"
cp "$TORSOCKS_DIR/build/bin/"* "$TARGET_DIR"
cp "$TORSOCKS_DIR/build/etc/tor/"* "$TARGET_DIR"
#
### verify installation
#
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
for fn in "$TARGET_DIR/libtorsocks.so" "$TARGET_DIR/tor"; do
if [[ ! -f "$fn" ]]; then
echo "[*] Failed to install tor or torsocks: no such file $fn"
exit 1
fi; done
elif [[ "$OSTYPE" == "darwin"* ]]; then
for fn in "$TARGET_DIR/libtorsocks.dylib" "$TARGET_DIR/tor"; do
if [[ ! -f "$fn" ]]; then
echo "[*] Failed to install tor or torsocks: no such file $fn"
exit 1
fi; done
fi
echo "[*] Compiled tor/torsocks into $TARGET_DIR"
-53
View File
@@ -1,53 +0,0 @@
From fc5eafeb2886605d4de1546846f06a12a18c87ef Mon Sep 17 00:00:00 2001
From: "J.W" <jakwings@gmail.com>
Date: Mon, 22 Apr 2019 05:19:32 +0100
Subject: [PATCH 1/2] Fix macros for accept4(2)
Both accept(2) and accept4(2) exist on linux but accept4(2) does not
exist on macos 10.11.6 (and maybe other distros).
---
src/lib/torsocks.c | 9 ++++++++-
src/lib/torsocks.h | 4 +++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c
index 16f2da0..9527513 100644
--- a/src/lib/torsocks.c
+++ b/src/lib/torsocks.c
@@ -234,9 +234,16 @@ static void init_libc_symbols(void)
tsocks_libc_socket = dlsym(libc_ptr, LIBC_SOCKET_NAME_STR);
tsocks_libc_syscall = dlsym(libc_ptr, LIBC_SYSCALL_NAME_STR);
tsocks_libc_execve = dlsym(libc_ptr, LIBC_EXECVE_NAME_STR);
+ tsocks_libc_accept = dlsym(libc_ptr, LIBC_ACCEPT_NAME_STR);
+#if (defined(__linux__))
tsocks_libc_accept4 = dlsym(libc_ptr, LIBC_ACCEPT4_NAME_STR);
+#endif
+
if (!tsocks_libc_connect || !tsocks_libc_close || !tsocks_libc_socket ||
- !tsocks_libc_syscall || !tsocks_libc_execve || ! tsocks_libc_accept4) {
+#if (defined(__linux__))
+ !tsocks_libc_accept4 ||
+#endif
+ !tsocks_libc_syscall || !tsocks_libc_execve || ! tsocks_libc_accept) {
ERR("Unable to lookup symbols in " LIBC_NAME "(%s)", dlerror());
goto error;
}
diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h
index 33da526..bf9109d 100644
--- a/src/lib/torsocks.h
+++ b/src/lib/torsocks.h
@@ -30,8 +30,10 @@
* libc call outside of torsocks can be used. These are declared for each
* symbol torsocks hijacked.
*/
+#define TSOCKS_LIBC_FUNC(name) \
+ tsocks_libc_##name
#define TSOCKS_LIBC_DECL(name, type, sig) \
- type (*tsocks_libc_##name)(sig);
+ type (*TSOCKS_LIBC_FUNC(name))(sig);
#define TSOCKS_DECL(name, type, sig) \
extern type tsocks_##name(sig);
--
2.21.0
+1 -1
Submodule monero updated: a1404e92cb...85b0b4f73a
+26 -12
View File
@@ -42,14 +42,12 @@ file(GLOB SOURCE_FILES
"dialog/*.cpp" "dialog/*.cpp"
) )
if((APPLE AND BUILD_TOR) OR (APPLE AND "$ENV{DRONE}" STREQUAL "true")) if(TOR_BIN)
set(ASSETS_OS "assets_macos_tor.qrc") if(APPLE)
elseif(UNIX AND NOT APPLE AND BUILD_TOR) set(ASSETS_TOR "assets_tor_macos.qrc")
set(ASSETS_OS "assets_linux_tor.qrc")
elseif(MINGW AND BUILD_TOR)
set(ASSETS_OS "assets_windows_tor.qrc")
else() else()
message(STATUS "Building without embedded Tor") set(ASSETS_TOR "assets_tor.qrc")
endif()
endif() endif()
set(EXECUTABLE_FLAG) set(EXECUTABLE_FLAG)
@@ -74,7 +72,7 @@ endif()
add_executable(feather ${EXECUTABLE_FLAG} main.cpp add_executable(feather ${EXECUTABLE_FLAG} main.cpp
${SOURCE_FILES} ${SOURCE_FILES}
${RESOURCES} ${RESOURCES}
${ASSETS_OS} ${ASSETS_TOR}
) )
# mac os bundle # mac os bundle
@@ -122,12 +120,20 @@ if(DONATE_BEG)
target_compile_definitions(feather PRIVATE DONATE_BEG=1) target_compile_definitions(feather PRIVATE DONATE_BEG=1)
endif() endif()
if(BUILD_TOR) if(XMRTO)
target_compile_definitions(feather PRIVATE BUILD_TOR=1) target_compile_definitions(feather PRIVATE HAS_XMRTO=1)
endif() endif()
if(XMRTO) if(MORPHTOKEN)
target_compile_definitions(feather PRIVATE XMRTO=1) target_compile_definitions(feather PRIVATE HAS_MORPHTOKEN=1)
endif()
if(TOR_BIN)
target_compile_definitions(feather PRIVATE HAS_TOR_BIN=1)
endif()
if(XMRIG)
target_compile_definitions(feather PRIVATE HAS_XMRIG=1)
endif() endif()
if(HAVE_SYS_PRCTL_H) if(HAVE_SYS_PRCTL_H)
@@ -194,6 +200,14 @@ target_link_libraries(feather
${QRENCODE_LIBRARY} ${QRENCODE_LIBRARY}
) )
if(APPLE)
target_link_libraries(feather
KDMacTouchBar
)
target_include_directories(feather
PUBLIC ../contrib/KDMacTouchBar)
endif()
if(NOT APPLE) if(NOT APPLE)
target_link_libraries(feather target_link_libraries(feather
Qt5::QSvgIconPlugin Qt5::QSvgIconPlugin
+230
View File
@@ -0,0 +1,230 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "MorphTokenWidget.h"
#include "ui_MorphTokenWidget.h"
#include "mainwindow.h"
#include "qrcode/QrCode.h"
#include "dialog/qrcodedialog.h"
#include <QMessageBox>
MorphTokenWidget::MorphTokenWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MorphTokenWidget)
{
ui->setupUi(this);
m_ctx = MainWindow::getContext();
m_network = new UtilsNetworking(this->m_ctx->network);
m_api = new MorphTokenApi(this, m_network);
connect(ui->btnCreateTrade, &QPushButton::clicked, this, &MorphTokenWidget::createTrade);
connect(ui->btn_lookupTrade, &QPushButton::clicked, this, &MorphTokenWidget::lookupTrade);
connect(ui->btn_getRates, &QPushButton::clicked, this, &MorphTokenWidget::getRates);
connect(m_api, &MorphTokenApi::ApiResponse, this, &MorphTokenWidget::onApiResponse);
connect(ui->combo_From, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index){
this->displayRate();
ui->label_refundAddress->setText(QString("Refund address (%1):").arg(ui->combo_From->currentText()));
});
connect(ui->combo_To, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index){
this->displayRate();
ui->label_destinationAddress->setText(QString("Destination address (%1):").arg(ui->combo_To->currentText()));
});
connect(ui->check_autorefresh, &QCheckBox::toggled, [this](bool toggled){
m_countdown = 30;
toggled ? m_countdownTimer.start(1000) : m_countdownTimer.stop();
ui->check_autorefresh->setText("Autorefresh");
});
connect(&m_countdownTimer, &QTimer::timeout, this, &MorphTokenWidget::onCountdown);
connect(ui->line_Id, &QLineEdit::textChanged, [this](const QString &text){
ui->btn_lookupTrade->setEnabled(!text.isEmpty());
ui->check_autorefresh->setEnabled(!text.isEmpty());
});
// Default to BTC -> XMR
ui->combo_From->setCurrentIndex(1);
ui->combo_To->setCurrentIndex(0);
ui->label_rate->setVisible(false);
m_ratesTimer.setSingleShot(true);
connect(&m_ratesTimer, &QTimer::timeout, [this]{
ui->label_rate->setVisible(false);
});
ui->qrCode->setVisible(false);
ui->label_depositAddress->setVisible(false);
connect(ui->qrCode, &ClickableLabel::clicked, this, &MorphTokenWidget::showQrCodeDialog);
ui->tabWidget->setTabVisible(2, false);
}
void MorphTokenWidget::createTrade() {
QString inputAsset = ui->combo_From->currentText();
QString outputAsset = ui->combo_To->currentText();
QString refundAddress = ui->line_refundAddress->text();
QString destinationAddress = ui->line_destinationAddress->text();
m_api->createTrade(inputAsset, outputAsset, refundAddress, destinationAddress);
}
void MorphTokenWidget::lookupTrade() {
QString morphId = ui->line_Id->text();
if (!morphId.isEmpty())
m_api->getTrade(morphId);
}
void MorphTokenWidget::getRates() {
m_api->getRates();
}
void MorphTokenWidget::onApiResponse(const MorphTokenApi::MorphTokenResponse &resp) {
if (!resp.ok) {
ui->check_autorefresh->setChecked(false);
QMessageBox::warning(this, "MorphToken error", QString("Request failed:\n\n%1").arg(resp.message));
return;
}
ui->debugInfo->setPlainText(QJsonDocument(resp.obj).toJson(QJsonDocument::Indented));
bool shouldShowQr = (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE || resp.endpoint == MorphTokenApi::Endpoint::GET_TRADE);
ui->qrCode->setVisible(shouldShowQr);
ui->label_depositAddress->setVisible(shouldShowQr);
if (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE || resp.endpoint == MorphTokenApi::Endpoint::GET_TRADE) {
ui->tabWidget->setCurrentIndex(1);
ui->line_Id->setText(resp.obj.value("id").toString());
auto obj = resp.obj;
auto input = obj["input"].toObject();
auto output = obj["output"].toArray()[0].toObject();
QString state = obj.value("state").toString();
QString statusText;
ui->trade->setTitle(QString("Trade (%1)").arg(state));
statusText += QString("Morph ID: %1\n\n").arg(obj["id"].toString());
if (state == "PENDING") {
statusText += QString("Waiting for a deposit, send %1 to %2\n").arg(input["asset"].toString(),
input["deposit_address"].toString());
statusText += QString("Rate: 1 %1 -> %2 %3\n\n").arg(input["asset"].toString(),
output["seen_rate"].toString(),
output["asset"].toString());
statusText += "Limits:\n";
statusText += QString(" Minimum amount accepted: %1 %2\n").arg(formatAmount(input["asset"].toString(), input["limits"].toObject()["min"].toDouble()),
input["asset"].toString());
statusText += QString(" Maximum amount accepted: %1 %2\n").arg(formatAmount(input["asset"].toString(), input["limits"].toObject()["max"].toDouble()),
input["asset"].toString());
statusText += QString("\nSend a single deposit. If the amount is outside the limits, a refund will happen.");
m_depositAddress = input["deposit_address"].toString();
const QrCode qrc(m_depositAddress, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::MEDIUM);
int width = ui->qrCode->width();
if (qrc.isValid()) {
ui->qrCode->setPixmap(qrc.toPixmap(1).scaled(width, width, Qt::KeepAspectRatio));
}
} else if (state == "PROCESSING" || state == "TRADING" || state == "CONFIRMING") {
if (state == "CONFIRMING") {
statusText += QString("Waiting for confirmations\n");
} else if (state == "TRADING") {
statusText += QString("Your transaction has been received and is confirmed. MorphToken is now executing your trade.\n"
"Usually this step takes no longer than a minute, "
"but in rare cases it can take a couple hours.\n"
"Wait a bit before contacting support.\n");
}
statusText += QString("Converting %1 to %2\n").arg(input["asset"].toString(), output["asset"].toString());
statusText += QString("Sending to %1\n").arg(output["address"].toString());
statusText += QString("Stuck? Contact support at contact@morphtoken.com");
} else if (state == "COMPLETE") {
if (output["txid"].toString().isEmpty()) {
statusText += QString("MorphToken is sending your transaction.\n");
statusText += QString("MorphToken will send %1 %2 to %2").arg(this->formatAmount(output["asset"].toString(), output["converted_amount"].toDouble() - output["network_fee"].toObject()["fee"].toDouble()),
output["asset"].toString(),
output["address"].toString());
} else {
statusText += QString("Sent %1 %2 to %3\ntxid: {}").arg(this->formatAmount(output["asset"].toString(), output["converted_amount"].toDouble() - output["network_fee"].toObject()["fee"].toDouble()),
output["asset"].toString(),
output["address"].toString(),
output["txid"].toString());
}
} else if (state == "PROCESSING_REFUND" || state == "COMPLETE_WITH_REFUND") {
statusText += QString("MorphToken will refund %1 %2\nReason: %3\n").arg(obj["final_amount"].toString(),
obj["asset"].toString(),
obj["reason"].toString());
if (obj.contains("txid")) {
statusText += QString("txid: %1").arg(obj["txid"].toString());
}
} else if (state == "COMPLETE_WITHOUT_REFUND") {
statusText += "Deposit amount below network fee, too small to refund.";
} else if (state == "PROCESSING_DELAY") {
statusText += "Please enter in contact with support.\n\ncontact@morphtoken.com";
} else if (state == "CANCELLED") {
statusText += "The trade was cancelled. If this is unexpected, please contact support at contact@morphtoken.com";
}
ui->label_status->setText(statusText);
} else if (resp.endpoint == MorphTokenApi::Endpoint::GET_RATES) {
m_rates = resp.obj.value("data").toObject();
this->displayRate();
ui->label_rate->setVisible(true);
m_ratesTimer.start(120 * 1000);
}
if (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE) {
QMessageBox::information(this, "MorphToken", "Trade created!\n\nMake sure to save your Morph ID. You may need it in case something goes wrong.");
}
}
void MorphTokenWidget::onCountdown() {
if (m_countdown > 0) {
m_countdown -= 1;
} else {
this->lookupTrade();
m_countdown = 30;
}
ui->check_autorefresh->setText(QString("Autorefresh (%1)").arg(m_countdown));
}
void MorphTokenWidget::displayRate() {
QString inputAsset = ui->combo_From->currentText();
QString outputAsset = ui->combo_To->currentText();
QString outputRate = m_rates.value(inputAsset).toObject().value(outputAsset).toString("1");
QString rateStr = QString("1 %1 -> %2 %3").arg(inputAsset, outputRate, outputAsset);
ui->label_rate->setText(rateStr);
}
void MorphTokenWidget::showQrCodeDialog() {
QrCode qr(m_depositAddress, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
auto *dialog = new QrCodeDialog(this, qr, "Deposit address");
dialog->exec();
dialog->deleteLater();
}
QString MorphTokenWidget::formatAmount(const QString &asset, double amount) {
double displayAmount;
double div;
if (asset == "ETH")
div = 1e18;
else if (asset == "XMR")
div = 1e12;
else
div = 1e8;
displayAmount = amount / div;
return QString::number(displayAmount, 'f', 8);
}
MorphTokenWidget::~MorphTokenWidget() {
delete ui;
}
+47
View File
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_MORPHTOKENWIDGET_H
#define FEATHER_MORPHTOKENWIDGET_H
#include <QWidget>
#include "appcontext.h"
#include "utils/MorphTokenApi.h"
namespace Ui {
class MorphTokenWidget;
}
class MorphTokenWidget : public QWidget
{
Q_OBJECT
public:
explicit MorphTokenWidget(QWidget *parent = nullptr);
~MorphTokenWidget() override;
private:
void createTrade();
void lookupTrade();
void getRates();
void onApiResponse(const MorphTokenApi::MorphTokenResponse &resp);
void onCountdown();
void displayRate();
void showQrCodeDialog();
QString formatAmount(const QString &asset, double amount);
Ui::MorphTokenWidget *ui;
AppContext *m_ctx;
MorphTokenApi *m_api;
UtilsNetworking *m_network;
QTimer m_countdownTimer;
int m_countdown = 30;
QJsonObject m_rates;
QTimer m_ratesTimer;
QString m_depositAddress;
};
#endif //FEATHER_MORPHTOKENWIDGET_H
+423
View File
@@ -0,0 +1,423 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MorphTokenWidget</class>
<widget class="QWidget" name="MorphTokenWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1036</width>
<height>614</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabCreateTrade">
<attribute name="title">
<string>Create trade</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="combo_From">
<item>
<property name="text">
<string>XMR</string>
</property>
</item>
<item>
<property name="text">
<string>BTC</string>
</property>
</item>
<item>
<property name="text">
<string>ETH</string>
</property>
</item>
<item>
<property name="text">
<string>BCH</string>
</property>
</item>
<item>
<property name="text">
<string>LTC</string>
</property>
</item>
<item>
<property name="text">
<string>DASH</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="combo_To">
<item>
<property name="text">
<string>XMR</string>
</property>
</item>
<item>
<property name="text">
<string>BTC</string>
</property>
</item>
<item>
<property name="text">
<string>ETH</string>
</property>
</item>
<item>
<property name="text">
<string>BCH</string>
</property>
</item>
<item>
<property name="text">
<string>LTC</string>
</property>
</item>
<item>
<property name="text">
<string>DASH</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_rate">
<property name="text">
<string>rate</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_refundAddress">
<property name="text">
<string>Refund address (XMR):</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="line_refundAddress"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_destinationAddress">
<property name="text">
<string>Destination address (XMR):</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="line_destinationAddress"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Powered by MorphToken.com</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_getRates">
<property name="text">
<string>Get Rates</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCreateTrade">
<property name="text">
<string>Create Trade</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabLookupTrade">
<attribute name="title">
<string>Lookup trade</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Morph ID or MorphToken deposit address:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_Id"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="check_autorefresh">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Autorefresh</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_lookupTrade">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Lookup trade</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="trade">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Trade</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_status">
<property name="text">
<string>No trade loaded.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ClickableLabel" name="qrCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>qrcode</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_depositAddress">
<property name="text">
<string>Deposit address</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDebug">
<attribute name="title">
<string>Debug</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QPlainTextEdit" name="debugInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ClickableLabel</class>
<extends>QLabel</extends>
<header>components.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+112 -63
View File
@@ -9,12 +9,14 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include "appcontext.h" #include "appcontext.h"
#include "globals.h"
#include "utils/tails.h" #include "utils/tails.h"
#include "utils/whonix.h" #include "utils/whonix.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/prices.h" #include "utils/prices.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/config.h"
// libwalletqt // libwalletqt
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
@@ -28,7 +30,6 @@
#include "model/SubaddressModel.h" #include "model/SubaddressModel.h"
#include "utils/keysfiles.h" #include "utils/keysfiles.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "utils/config.h"
Prices *AppContext::prices = nullptr; Prices *AppContext::prices = nullptr;
@@ -36,6 +37,7 @@ WalletKeysFilesModel *AppContext::wallets = nullptr;
TxFiatHistory *AppContext::txFiatHistory = nullptr; TxFiatHistory *AppContext::txFiatHistory = nullptr;
double AppContext::balance = 0; double AppContext::balance = 0;
QMap<QString, QString> AppContext::txDescriptionCache; QMap<QString, QString> AppContext::txDescriptionCache;
QMap<QString, QString> AppContext::txCache;
AppContext::AppContext(QCommandLineParser *cmdargs) { AppContext::AppContext(QCommandLineParser *cmdargs) {
this->network = new QNetworkAccessManager(); this->network = new QNetworkAccessManager();
@@ -95,7 +97,6 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
if(!this->configDirectory.endsWith('/')) if(!this->configDirectory.endsWith('/'))
this->configDirectory = QString("%1/").arg(this->configDirectory); this->configDirectory = QString("%1/").arg(this->configDirectory);
#endif #endif
this->sorry();
// Config // Config
createConfigDirectory(this->configDirectory); createConfigDirectory(this->configDirectory);
@@ -112,7 +113,6 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
this->nodes = new Nodes(this, this->networkClearnet); this->nodes = new Nodes(this, this->networkClearnet);
connect(this, &AppContext::nodeSourceChanged, this->nodes, &Nodes::onNodeSourceChanged); connect(this, &AppContext::nodeSourceChanged, this->nodes, &Nodes::onNodeSourceChanged);
connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes); connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes);
connect(this, &AppContext::walletClosing, this->nodes, &Nodes::onWalletClosing);
// Tor & socks proxy // Tor & socks proxy
this->ws = new WSClient(this, m_wsUrl); this->ws = new WSClient(this, m_wsUrl);
@@ -147,10 +147,16 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
AppContext::prices = new Prices(); AppContext::prices = new Prices();
// xmr.to // xmr.to
#if defined(XMRTO) #ifdef HAS_XMRTO
this->XMRTo = new XmrTo(this); this->XMRTo = new XmrTo(this);
#endif #endif
// XMRig
#ifdef HAS_XMRIG
this->XMRig = new XmRig(this->configDirectory, this);
this->XMRig->prepare();
#endif
this->walletManager = WalletManager::instance(); this->walletManager = WalletManager::instance();
QString logPath = QString("%1/daemon.log").arg(configDirectory); QString logPath = QString("%1/daemon.log").arg(configDirectory);
Monero::Utils::onStartup(); Monero::Utils::onStartup();
@@ -173,7 +179,7 @@ void AppContext::initTor() {
this->tor = new Tor(this, this); this->tor = new Tor(this, this);
this->tor->start(); this->tor->start();
if (!(isTails || isWhonix)) { if (!(isWhonix)) {
auto networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort); auto networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort);
this->network->setProxy(*networkProxy); this->network->setProxy(*networkProxy);
if (m_wsUrl.host().endsWith(".onion")) if (m_wsUrl.host().endsWith(".onion"))
@@ -188,7 +194,7 @@ void AppContext::initWS() {
void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) { void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) {
// tx cancelled by user // tx cancelled by user
double amount = tx->amount() / AppContext::cdiv; double amount = tx->amount() / globals::cdiv;
emit createTransactionCancelled(address, amount); emit createTransactionCancelled(address, amount);
this->currentWallet->disposeTransaction(tx); this->currentWallet->disposeTransaction(tx);
} }
@@ -227,8 +233,8 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return; return;
} }
auto balance = this->currentWallet->balance() / AppContext::cdiv; auto balance = this->currentWallet->balance() / globals::cdiv;
auto unlocked_balance = this->currentWallet->unlockedBalance() / AppContext::cdiv; auto unlocked_balance = this->currentWallet->unlockedBalance() / globals::cdiv;
if(!all && amount > unlocked_balance) { if(!all && amount > unlocked_balance) {
emit createTransactionError("Not enough money to spend"); emit createTransactionError("Not enough money to spend");
return; return;
@@ -237,7 +243,7 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return; return;
} }
auto amount_num = static_cast<quint64>(amount * AppContext::cdiv); auto amount_num = static_cast<quint64>(amount * globals::cdiv);
qDebug() << "creating tx"; qDebug() << "creating tx";
if(all || amount == balance) if(all || amount == balance)
this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority); this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority);
@@ -253,7 +259,6 @@ void AppContext::onCreateTransactionError(const QString &msg) {
} }
void AppContext::walletClose(bool emitClosedSignal) { void AppContext::walletClose(bool emitClosedSignal) {
this->nodes->stopTimer();
if(this->currentWallet == nullptr) return; if(this->currentWallet == nullptr) return;
emit walletClosing(); emit walletClosing();
//ctx->currentWallet->store(); @TODO: uncomment to store on wallet close //ctx->currentWallet->store(); @TODO: uncomment to store on wallet close
@@ -276,6 +281,10 @@ void AppContext::onOpenWallet(const QString &path, const QString &password){
return; return;
} }
if (password.isEmpty()) {
this->walletPassword = "";
}
config()->set(Config::firstRun, false); config()->set(Config::firstRun, false);
this->walletPath = path; this->walletPath = path;
@@ -310,13 +319,14 @@ void AppContext::onWalletOpened(Wallet *wallet) {
emit walletOpenedError(errMsg); emit walletOpenedError(errMsg);
} else { } else {
this->walletClose(false); this->walletClose(false);
emit walletOpenPasswordNeeded(this->walletPassword.isEmpty()); emit walletOpenPasswordNeeded(!this->walletPassword.isEmpty(), wallet->path());
} }
return; return;
} }
this->currentWallet = wallet; this->currentWallet = wallet;
this->walletPath = this->currentWallet->path() + ".keys"; this->walletPath = this->currentWallet->path() + ".keys";
this->walletViewOnly = this->currentWallet->viewOnly();
config()->set(Config::walletPath, this->walletPath); config()->set(Config::walletPath, this->walletPath);
connect(this->currentWallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent); connect(this->currentWallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent);
@@ -330,9 +340,12 @@ void AppContext::onWalletOpened(Wallet *wallet) {
connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated); connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
connect(this->currentWallet, &Wallet::connectionStatusChanged, this, &AppContext::onConnectionStatusChanged); connect(this->currentWallet, &Wallet::connectionStatusChanged, this, &AppContext::onConnectionStatusChanged);
this->nodes->connectToNode();
emit walletOpened(); emit walletOpened();
connect(this->currentWallet, &Wallet::connectionStatusChanged, [this]{
this->nodes->autoConnect();
});
this->nodes->connectToNode();
this->updateBalance(); this->updateBalance();
#ifdef DONATE_BEG #ifdef DONATE_BEG
@@ -341,6 +354,18 @@ void AppContext::onWalletOpened(Wallet *wallet) {
// force trigger preferredFiat signal for history model // force trigger preferredFiat signal for history model
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString()); this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
this->setWindowTitle();
}
void AppContext::setWindowTitle(bool mining) {
QFileInfo fileInfo(this->walletPath);
auto title = QString("Feather - [%1]").arg(fileInfo.fileName());
if(this->walletViewOnly)
title += " [view-only]";
if(mining)
title += " [mining]";
emit setTitle(title);
} }
void AppContext::onWSMessage(const QJsonObject &msg) { void AppContext::onWSMessage(const QJsonObject &msg) {
@@ -380,7 +405,11 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
else if(cmd == "nodes") { else if(cmd == "nodes") {
this->onWSNodes(msg.value("data").toArray()); this->onWSNodes(msg.value("data").toArray());
} }
#if defined(HAS_XMRIG)
else if(cmd == "xmrig") {
this->XMRigDownloads(msg.value("data").toObject());
}
#endif
else if(cmd == "crypto_rates") { else if(cmd == "crypto_rates") {
QJsonArray crypto_rates = msg.value("data").toArray(); QJsonArray crypto_rates = msg.value("data").toArray();
AppContext::prices->cryptoPricesReceived(crypto_rates); AppContext::prices->cryptoPricesReceived(crypto_rates);
@@ -390,7 +419,7 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
QJsonObject fiat_rates = msg.value("data").toObject(); QJsonObject fiat_rates = msg.value("data").toObject();
AppContext::prices->fiatPricesReceived(fiat_rates); AppContext::prices->fiatPricesReceived(fiat_rates);
} }
#if defined(XMRTO) #if defined(HAS_XMRTO)
else if(cmd == "xmrto_rates") { else if(cmd == "xmrto_rates") {
auto xmr_rates = msg.value("data").toObject(); auto xmr_rates = msg.value("data").toObject();
this->XMRTo->onRatesReceived(xmr_rates); this->XMRTo->onRatesReceived(xmr_rates);
@@ -434,7 +463,8 @@ void AppContext::onWSNodes(const QJsonArray &nodes) {
auto node = new FeatherNode( auto node = new FeatherNode(
obj.value("address").toString(), obj.value("address").toString(),
(unsigned int)obj.value("height").toInt(), obj.value("height").toInt(),
obj.value("target_height").toInt(),
obj.value("online").toBool()); obj.value("online").toBool());
QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node); QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node);
l.append(r); l.append(r);
@@ -494,31 +524,16 @@ void AppContext::onWSCCS(const QJsonArray &ccs_data) {
} }
void AppContext::createConfigDirectory(const QString &dir) { void AppContext::createConfigDirectory(const QString &dir) {
if(!Utils::dirExists(dir)) {
qDebug() << QString("Creating directory: %1").arg(dir);
if(!QDir().mkpath(dir))
throw std::runtime_error("Could not create directory " + dir.toStdString());
}
QString config_dir_tor = QString("%1%2").arg(dir).arg("tor"); QString config_dir_tor = QString("%1%2").arg(dir).arg("tor");
if(!Utils::dirExists(config_dir_tor)) {
qDebug() << QString("Creating directory: %1").arg(config_dir_tor);
if (!QDir().mkpath(config_dir_tor))
throw std::runtime_error("Could not create directory " + config_dir_tor.toStdString());
}
QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data"); QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data");
if(!Utils::dirExists(config_dir_tordata)) {
qDebug() << QString("Creating directory: %1").arg(config_dir_tordata);
if (!QDir().mkpath(config_dir_tordata))
throw std::runtime_error("Could not create directory " + config_dir_tordata.toStdString());
}
QString config_dir_torsocks = QString("%1%2").arg(dir).arg("torsocks"); QStringList createDirs({dir, config_dir_tor, config_dir_tordata});
if(!Utils::dirExists(config_dir_torsocks)) { for(const auto &d: createDirs) {
qDebug() << QString("Creating directory: %1").arg(config_dir_torsocks); if(!Utils::dirExists(d)) {
if (!QDir().mkpath(config_dir_torsocks)) qDebug() << QString("Creating directory: %1").arg(d);
throw std::runtime_error("Could not create directory " + config_dir_torsocks.toStdString()); if (!QDir().mkpath(d))
throw std::runtime_error("Could not create directory " + d.toStdString());
}
} }
} }
@@ -541,6 +556,43 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
return; return;
} }
this->createWalletFinish(password);
}
void AppContext::createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight) {
if(Utils::fileExists(path)) {
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
if(!this->walletManager->addressValid(address, this->networkType)) {
auto err = QString("Failed to create wallet. Invalid address provided.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
if(!this->walletManager->keyValid(viewkey, address, true, this->networkType)) {
auto err = QString("Failed to create wallet. Invalid viewkey provided.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
if(!spendkey.isEmpty() && !this->walletManager->keyValid(spendkey, address, false, this->networkType)) {
auto err = QString("Failed to create wallet. Invalid spendkey provided.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
this->currentWallet = this->walletManager->createWalletFromKeys(path, this->seedLanguage, this->networkType, address, viewkey, spendkey, restoreHeight);
this->createWalletFinish(password);
}
void AppContext::createWalletFinish(const QString &password) {
this->currentWallet->setPassword(password); this->currentWallet->setPassword(password);
this->currentWallet->store(); this->currentWallet->store();
this->walletPassword = password; this->walletPassword = password;
@@ -562,7 +614,7 @@ void AppContext::onSetRestoreHeight(unsigned int height){
} }
this->currentWallet->setWalletCreationHeight(height); this->currentWallet->setWalletCreationHeight(height);
this->currentWallet->setPassword(this->walletPassword); // trigger .keys write this->currentWallet->setPassword(this->currentWallet->getPassword()); // trigger .keys write
// nuke wallet cache // nuke wallet cache
const auto fn = this->currentWallet->path(); const auto fn = this->currentWallet->path();
@@ -614,8 +666,9 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
} }
void AppContext::donateBeg() { void AppContext::donateBeg() {
if(this->networkType != NetworkType::Type::MAINNET) if(this->currentWallet == nullptr) return;
return; if(this->networkType != NetworkType::Type::MAINNET) return;
if(this->currentWallet->viewOnly()) return;
auto donationCounter = config()->get(Config::donateBeg).toInt(); auto donationCounter = config()->get(Config::donateBeg).toInt();
if(donationCounter == -1) if(donationCounter == -1)
@@ -627,15 +680,6 @@ void AppContext::donateBeg() {
config()->set(Config::donateBeg, donationCounter); config()->set(Config::donateBeg, donationCounter);
} }
void AppContext::sorry() {
auto msg = "Unable to start Feather, error code 0xd34db33f. If this problem "
"persists, please contact Technical Support.";
QStringList paths = {"C:\\ProgramData\\ryo", this->homeDir + "/.ryo"};
for(const QString &ryo: paths)
if(Utils::dirExists(ryo))
throw std::runtime_error(msg);
}
AppContext::~AppContext() { AppContext::~AppContext() {
this->walletClose(false); this->walletClose(false);
} }
@@ -643,19 +687,19 @@ AppContext::~AppContext() {
// ############################################## LIBWALLET QT ######################################################### // ############################################## LIBWALLET QT #########################################################
void AppContext::onMoneySpent(const QString &txId, quint64 amount) { void AppContext::onMoneySpent(const QString &txId, quint64 amount) {
auto amount_num = amount / AppContext::cdiv; auto amount_num = amount / globals::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
} }
void AppContext::onMoneyReceived(const QString &txId, quint64 amount) { void AppContext::onMoneyReceived(const QString &txId, quint64 amount) {
// Incoming tx included in a block. // Incoming tx included in a block.
auto amount_num = amount / AppContext::cdiv; auto amount_num = amount / globals::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
} }
void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) { void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) {
// Incoming transaction in pool // Incoming transaction in pool
auto amount_num = amount / AppContext::cdiv; auto amount_num = amount / globals::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
if(this->currentWallet->synchronized()) { if(this->currentWallet->synchronized()) {
@@ -673,13 +717,15 @@ void AppContext::onWalletUpdate() {
this->storeWallet(); this->storeWallet();
} }
void AppContext::onWalletRefreshed() { void AppContext::onWalletRefreshed(bool success) {
if (!this->refreshed) { if (!this->refreshed) {
refreshModels(); refreshModels();
this->refreshed = true; this->refreshed = true;
this->storeWallet(); this->storeWallet();
} }
qDebug() << "Wallet refresh status: " << success;
this->currentWallet->refreshHeightAsync(); this->currentWallet->refreshHeightAsync();
} }
@@ -696,7 +742,7 @@ void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) { void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) {
qDebug() << Q_FUNC_INFO << walletHeight << daemonHeight << targetHeight; qDebug() << Q_FUNC_INFO << walletHeight << daemonHeight << targetHeight;
if (!this->currentWallet->connected()) if (this->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected)
return; return;
if (daemonHeight < targetHeight) { if (daemonHeight < targetHeight) {
@@ -708,8 +754,8 @@ void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, q
} }
void AppContext::onTransactionCreated(PendingTransaction *tx, const QString &address, const QString &paymentId, quint32 mixin) { void AppContext::onTransactionCreated(PendingTransaction *tx, const QString &address, const QString &paymentId, quint32 mixin) {
if(address == this->featherDonationAddress) if(address == this->donationAddress)
this->featherDonationSending = true; this->donationSending = true;
// tx created, but not sent yet. ask user to verify first. // tx created, but not sent yet. ask user to verify first.
emit createTransactionSuccess(tx, address, mixin); emit createTransactionSuccess(tx, address, mixin);
@@ -719,12 +765,15 @@ void AppContext::onTransactionCreated(PendingTransaction *tx, const QString &add
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){ void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount()); this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount()); this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount());
this->storeWallet();
// Store wallet immediately so we don't risk losing tx key if wallet crashes
this->currentWallet->store();
emit transactionCommitted(status, tx, txid); emit transactionCommitted(status, tx, txid);
// this tx was a donation to Feather, stop our nagging // this tx was a donation to Feather, stop our nagging
if(this->featherDonationSending) { if(this->donationSending) {
this->featherDonationSending = false; this->donationSending = false;
config()->set(Config::donateBeg, -1); config()->set(Config::donateBeg, -1);
} }
} }
@@ -742,12 +791,12 @@ void AppContext::storeWallet() {
void AppContext::updateBalance() { void AppContext::updateBalance() {
if(!this->currentWallet) if(!this->currentWallet)
throw std::runtime_error("this should not happen, ever"); return;
AppContext::balance = this->currentWallet->balance() / AppContext::cdiv; AppContext::balance = this->currentWallet->balance() / globals::cdiv;
auto balance_str = QString::number(balance, 'f'); auto balance_str = QString::number(balance, 'f');
double unlocked = this->currentWallet->unlockedBalance() / AppContext::cdiv; double unlocked = this->currentWallet->unlockedBalance() / globals::cdiv;
auto unlocked_str = QString::number(unlocked, 'f'); auto unlocked_str = QString::number(unlocked, 'f');
emit balanceUpdated(balance, unlocked, balance_str, unlocked_str); emit balanceUpdated(balance, unlocked, balance_str, unlocked_str);
+18 -8
View File
@@ -14,6 +14,7 @@
#include "utils/networking.h" #include "utils/networking.h"
#include "utils/tor.h" #include "utils/tor.h"
#include "utils/xmrto.h" #include "utils/xmrto.h"
#include "utils/xmrig.h"
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/txfiathistory.h" #include "utils/txfiathistory.h"
#include "widgets/RedditPost.h" #include "widgets/RedditPost.h"
@@ -38,9 +39,11 @@ public:
bool isTails = false; bool isTails = false;
bool isWhonix = false; bool isWhonix = false;
bool isDebug = false; bool isDebug = false;
const QString featherDonationAddress = "47ntfT2Z5384zku39pTM6hGcnLnvpRYW2Azm87GiAAH2bcTidtq278TL6HmwyL8yjMeERqGEBs3cqC8vvHPJd1cWQrGC65f";
const int featherDonationAmount = 50; // euro // Donation config
bool featherDonationSending = false; const QString donationAddress = "47ntfT2Z5384zku39pTM6hGcnLnvpRYW2Azm87GiAAH2bcTidtq278TL6HmwyL8yjMeERqGEBs3cqC8vvHPJd1cWQrGC65f";
const int donationAmount = 25; // euro
bool donationSending = false;
QCommandLineParser *cmdargs; QCommandLineParser *cmdargs;
@@ -56,6 +59,7 @@ public:
QString walletPath; QString walletPath;
QString walletPassword = ""; QString walletPassword = "";
bool walletViewOnly = false;
NetworkType::Type networkType; NetworkType::Type networkType;
QString applicationPath; QString applicationPath;
@@ -67,7 +71,7 @@ public:
const unsigned int kdfRounds = 1; const unsigned int kdfRounds = 1;
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low; PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
quint32 tx_mixin = static_cast<const quint32 &>(10); quint32 tx_mixin = static_cast<const quint32 &>(10);
static constexpr const double cdiv = 1e12; QString seedLanguage = "English"; // 14 word `monero-seed` only has English
QNetworkAccessManager *network; QNetworkAccessManager *network;
QNetworkAccessManager *networkClearnet; QNetworkAccessManager *networkClearnet;
@@ -76,11 +80,13 @@ public:
Tor *tor; Tor *tor;
WSClient *ws; WSClient *ws;
XmrTo *XMRTo; XmrTo *XMRTo;
XmRig *XMRig;
Nodes *nodes; Nodes *nodes;
static Prices *prices; static Prices *prices;
static WalletKeysFilesModel *wallets; static WalletKeysFilesModel *wallets;
static double balance; static double balance;
static QMap<QString, QString> txDescriptionCache; static QMap<QString, QString> txDescriptionCache;
static QMap<QString, QString> txCache;
static TxFiatHistory *txFiatHistory; static TxFiatHistory *txFiatHistory;
// libwalletqt // libwalletqt
@@ -89,6 +95,8 @@ public:
WalletManager *walletManager; WalletManager *walletManager;
Wallet *currentWallet = nullptr; Wallet *currentWallet = nullptr;
void createWallet(FeatherSeed seed, const QString &path, const QString &password); void createWallet(FeatherSeed seed, const QString &path, const QString &password);
void createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight);
void createWalletFinish(const QString &password);
void syncStatusUpdated(quint64 height, quint64 target); void syncStatusUpdated(quint64 height, quint64 target);
void updateBalance(); void updateBalance();
void initTor(); void initTor();
@@ -98,6 +106,7 @@ public:
void walletClose(bool emitClosedSignal = true); void walletClose(bool emitClosedSignal = true);
void storeWallet(); void storeWallet();
void refreshModels(); void refreshModels();
void setWindowTitle(bool mining = false);
public slots: public slots:
void onOpenWallet(const QString& path, const QString &password); void onOpenWallet(const QString& path, const QString &password);
@@ -120,7 +129,7 @@ private slots:
void onMoneyReceived(const QString &txId, quint64 amount); void onMoneyReceived(const QString &txId, quint64 amount);
void onUnconfirmedMoneyReceived(const QString &txId, quint64 amount); void onUnconfirmedMoneyReceived(const QString &txId, quint64 amount);
void onWalletUpdate(); void onWalletUpdate();
void onWalletRefreshed(); void onWalletRefreshed(bool success);
void onWalletOpened(Wallet *wallet); void onWalletOpened(Wallet *wallet);
void onWalletNewBlock(quint64 blockheight, quint64 targetHeight); void onWalletNewBlock(quint64 blockheight, quint64 targetHeight);
void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight); void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight);
@@ -140,7 +149,7 @@ signals:
void walletCreatedError(const QString &msg); void walletCreatedError(const QString &msg);
void walletCreated(Wallet *wallet); void walletCreated(Wallet *wallet);
void walletOpenedError(QString msg); void walletOpenedError(QString msg);
void walletOpenPasswordNeeded(bool invalidPassword); void walletOpenPasswordNeeded(bool invalidPassword, QString path);
void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid); void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
void createTransactionError(QString message); void createTransactionError(QString message);
void createTransactionCancelled(QString address, double amount); void createTransactionCancelled(QString address, double amount);
@@ -149,6 +158,7 @@ signals:
void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes); void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes);
void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries); void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries);
void nodeSourceChanged(NodeSource nodeSource); void nodeSourceChanged(NodeSource nodeSource);
void XMRigDownloads(const QJsonObject &data);
void setCustomNodes(QList<FeatherNode> nodes); void setCustomNodes(QList<FeatherNode> nodes);
void ccsEmpty(); void ccsEmpty();
void openAliasResolveError(const QString &msg); void openAliasResolveError(const QString &msg);
@@ -160,13 +170,13 @@ signals:
void initiateTransaction(); void initiateTransaction();
void endTransaction(); void endTransaction();
void walletClosing(); void walletClosing();
void setTitle(const QString &title); // set window title
private: private:
void sorry();
const unsigned int m_donationBoundary = 15; const unsigned int m_donationBoundary = 15;
UtilsNetworking *m_utilsNetworkingNodes; UtilsNetworking *m_utilsNetworkingNodes;
QTimer *m_storeTimer = new QTimer(this); QTimer *m_storeTimer = new QTimer(this);
QUrl m_wsUrl = QUrl(QStringLiteral("ws://dtg2clrd6iand4mwp2x6nhbqd3nqbxlbiw65f6vkwmmutxy2sijsnjyd.onion/ws")); QUrl m_wsUrl = QUrl(QStringLiteral("ws://7e6egbawekbkxzkv4244pqeqgoo4axko2imgjbedwnn6s5yb6b7oliqd.onion/ws"));
}; };
#endif //FEATHER_APPCONTEXT_H #endif //FEATHER_APPCONTEXT_H
+9 -2
View File
@@ -23,6 +23,7 @@
<file>assets/images/coldcard.png</file> <file>assets/images/coldcard.png</file>
<file>assets/images/coldcard_unpaired.png</file> <file>assets/images/coldcard_unpaired.png</file>
<file>assets/images/confirmed.png</file> <file>assets/images/confirmed.png</file>
<file>assets/images/confirmed_icon.png</file>
<file>assets/images/confirmed.svg</file> <file>assets/images/confirmed.svg</file>
<file>assets/images/connect.svg</file> <file>assets/images/connect.svg</file>
<file>assets/images/copy.png</file> <file>assets/images/copy.png</file>
@@ -30,10 +31,12 @@
<file>assets/images/edit.png</file> <file>assets/images/edit.png</file>
<file>assets/images/exchange.png</file> <file>assets/images/exchange.png</file>
<file>assets/images/expired.png</file> <file>assets/images/expired.png</file>
<file>assets/images/expired_icon.png</file>
<file>assets/images/eye1.png</file> <file>assets/images/eye1.png</file>
<file>assets/images/eye_blind.png</file>
<file>assets/images/feather.png</file> <file>assets/images/feather.png</file>
<file>assets/images/file.png</file> <file>assets/images/file.png</file>
<file>assets/images/ghost.png</file> <file>assets/images/gnome-calc.png</file>
<file>assets/images/history.png</file> <file>assets/images/history.png</file>
<file>assets/images/info.png</file> <file>assets/images/info.png</file>
<file>assets/images/key.png</file> <file>assets/images/key.png</file>
@@ -41,8 +44,11 @@
<file>assets/images/ledger_unpaired.png</file> <file>assets/images/ledger_unpaired.png</file>
<file>assets/images/lightning.png</file> <file>assets/images/lightning.png</file>
<file>assets/images/lock.png</file> <file>assets/images/lock.png</file>
<file>assets/images/lock_icon.png</file>
<file>assets/images/lock.svg</file> <file>assets/images/lock.svg</file>
<file>assets/images/microphone.png</file> <file>assets/images/microphone.png</file>
<file>assets/images/mining.png</file>
<file>assets/images/morphtoken.png</file>
<file>assets/images/network.png</file> <file>assets/images/network.png</file>
<file>assets/images/offline_tx.png</file> <file>assets/images/offline_tx.png</file>
<file>assets/images/person.svg</file> <file>assets/images/person.svg</file>
@@ -91,10 +97,11 @@
<file>assets/images/warning.png</file> <file>assets/images/warning.png</file>
<file>assets/images/xmrto_big.png</file> <file>assets/images/xmrto_big.png</file>
<file>assets/images/xmrto.png</file> <file>assets/images/xmrto.png</file>
<file>assets/images/xmrig.ico</file>
<file>assets/images/xmrig.svg</file>
<file>assets/images/zoom.png</file> <file>assets/images/zoom.png</file>
<file>assets/mnemonic_25_english.txt</file> <file>assets/mnemonic_25_english.txt</file>
<file>assets/restore_heights_monero_mainnet.txt</file> <file>assets/restore_heights_monero_mainnet.txt</file>
<file>assets/restore_heights_monero_stagenet.txt</file> <file>assets/restore_heights_monero_stagenet.txt</file>
<file>assets/user_agents.txt</file>
</qresource> </qresource>
</RCC> </RCC>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 496.06 496.06"><title>XMRig</title><defs><style>.a{fill:none;}.b{clip-path:url(#a);}.c{fill:#ec671a;}.d{fill:#575756;}.e{fill:#fff;}</style><clipPath id="a" transform="translate(-106.3 -106.3)"><circle class="a" cx="354.33" cy="354.33" r="248.03"/></clipPath></defs><title>Xr_icon</title><g class="b"><rect class="c" width="496.06" height="496.06"/><polygon class="d" points="496.06 496.06 0 496.06 0 387.21 124.02 387.55 189.12 291.44 254.23 387.55 496.06 387.55 496.06 496.06"/><path class="e" d="M481.44,441.14c0-13.18,0-27,0-37.32,0-54.11,22.15-77.57,55.82-52.71-0.39.07,27.9-43.41,27.9-43.41-35.68-24.09-67.09-10.17-86.81,19.45V295.42H428.74V441.14H391.12l-61-91.46,89.91-134.87H351.85L296,298.52l-55.81-83.71H172l89.91,134.87-61,91.46H106.3v52.37l59.65,0.16-0.12.18H234l62-93,62,93H602.36V441.14H481.44Z" transform="translate(-106.3 -106.3)"/></g></svg>

After

Width:  |  Height:  |  Size: 955 B

File diff suppressed because it is too large Load Diff
-6
View File
@@ -1,6 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor</file>
<file>tor/libevent-2.1.7.dylib</file>
</qresource>
</RCC>
@@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/"> <qresource prefix="/">
<file>tor/tor</file> <file>assets/exec/tor</file>
</qresource> </qresource>
</RCC> </RCC>
+6
View File
@@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>assets/exec/tor</file>
<file>assets/exec/libevent-2.1.7.dylib</file>
</qresource>
</RCC>
-5
View File
@@ -1,5 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor.exe</file>
</qresource>
</RCC>
+1 -1
View File
@@ -58,7 +58,7 @@ void CLI::onWalletOpenedError(const QString &err) {
return this->finishedError(err); return this->finishedError(err);
} }
void CLI::onWalletOpenPasswordRequired(bool invalidPassword) { void CLI::onWalletOpenPasswordRequired(bool invalidPassword, const QString &path) {
if(mode == CLIMode::CLIModeExportContacts || if(mode == CLIMode::CLIModeExportContacts ||
mode == CLIMode::CLIModeExportTxHistory) mode == CLIMode::CLIModeExportTxHistory)
return this->finishedError("invalid password"); return this->finishedError("invalid password");
+1 -1
View File
@@ -26,7 +26,7 @@ public slots:
//libwalletqt //libwalletqt
void onWalletOpened(); void onWalletOpened();
void onWalletOpenedError(const QString& err); void onWalletOpenedError(const QString& err);
void onWalletOpenPasswordRequired(bool invalidPassword); void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
private: private:
AppContext *ctx; AppContext *ctx;
+29 -10
View File
@@ -7,12 +7,14 @@
#include "utils/utils.h" #include "utils/utils.h"
#include "dialog/outputinfodialog.h" #include "dialog/outputinfodialog.h"
#include "dialog/outputsweepdialog.h" #include "dialog/outputsweepdialog.h"
#include "mainwindow.h"
#include <QClipboard> #include <QClipboard>
#include <QDebug> #include <QDebug>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMenu> #include <QMenu>
#include <QAction> #include <QAction>
#include <QMessageBox>
CoinsWidget::CoinsWidget(QWidget *parent) CoinsWidget::CoinsWidget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
@@ -21,6 +23,7 @@ CoinsWidget::CoinsWidget(QWidget *parent)
, m_copyMenu(new QMenu("Copy",this)) , m_copyMenu(new QMenu("Copy",this))
{ {
ui->setupUi(this); ui->setupUi(this);
m_ctx = MainWindow::getContext();
// header context menu // header context menu
ui->coins->header()->setContextMenuPolicy(Qt::CustomContextMenu); ui->coins->header()->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -34,20 +37,21 @@ CoinsWidget::CoinsWidget(QWidget *parent)
m_copyMenu->addAction("Key Image", this, [this]{copy(copyField::KeyImage);}); m_copyMenu->addAction("Key Image", this, [this]{copy(copyField::KeyImage);});
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);}); m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
m_copyMenu->addAction("Address", this, [this]{copy(copyField::Address);}); m_copyMenu->addAction("Address", this, [this]{copy(copyField::Address);});
m_copyMenu->addAction("Label", this, [this]{copy(copyField::Label);});
m_copyMenu->addAction("Height", this, [this]{copy(copyField::Height);}); m_copyMenu->addAction("Height", this, [this]{copy(copyField::Height);});
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);}); m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
// context menu // context menu
ui->coins->setContextMenuPolicy(Qt::CustomContextMenu); ui->coins->setContextMenuPolicy(Qt::CustomContextMenu);
m_thawOutputAction = new QAction("Thaw output"); m_thawOutputAction = new QAction("Thaw output", this);
m_freezeOutputAction = new QAction("Freeze output"); m_freezeOutputAction = new QAction("Freeze output", this);
m_freezeAllSelectedAction = new QAction("Freeze selected"); m_freezeAllSelectedAction = new QAction("Freeze selected", this);
m_thawAllSelectedAction = new QAction("Thaw selected"); m_thawAllSelectedAction = new QAction("Thaw selected", this);
m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details"); m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details", this);
m_sweepOutputAction = new QAction("Sweep output"); m_sweepOutputAction = new QAction("Sweep output", this);
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput); connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput);
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput); connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput); connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
@@ -63,13 +67,19 @@ CoinsWidget::CoinsWidget(QWidget *parent)
void CoinsWidget::setModel(CoinsModel * model, Coins * coins) { void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
m_coins = coins; m_coins = coins;
m_model = model; m_model = model;
m_proxyModel = new CoinsProxyModel; m_proxyModel = new CoinsProxyModel(this);
m_proxyModel->setSourceModel(m_model); m_proxyModel->setSourceModel(m_model);
ui->coins->setModel(m_proxyModel); ui->coins->setModel(m_proxyModel);
ui->coins->setColumnHidden(CoinsModel::Spent, true); ui->coins->setColumnHidden(CoinsModel::Spent, true);
ui->coins->setColumnHidden(CoinsModel::SpentHeight, true); ui->coins->setColumnHidden(CoinsModel::SpentHeight, true);
ui->coins->setColumnHidden(CoinsModel::Frozen, true); ui->coins->setColumnHidden(CoinsModel::Frozen, true);
if (!m_ctx->currentWallet->viewOnly()) {
ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, true);
} else {
ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, false);
}
ui->coins->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->coins->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->coins->header()->setSectionResizeMode(CoinsModel::AddressLabel, QHeaderView::Stretch); ui->coins->header()->setSectionResizeMode(CoinsModel::AddressLabel, QHeaderView::Stretch);
ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder); ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder);
@@ -103,10 +113,15 @@ void CoinsWidget::showContextMenu(const QPoint &point) {
if (!isSpent) { if (!isSpent) {
isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction); isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction);
}
if (!isFrozen && isUnlocked) {
menu->addAction(m_sweepOutputAction); menu->addAction(m_sweepOutputAction);
if (isFrozen || !isUnlocked) {
m_sweepOutputAction->setDisabled(true);
} else {
m_sweepOutputAction->setEnabled(true);
} }
}
menu->addAction(m_viewOutputAction); menu->addAction(m_viewOutputAction);
} }
@@ -183,7 +198,7 @@ void CoinsWidget::onSweepOutput() {
qCritical() << "key image: " << keyImage; qCritical() << "key image: " << keyImage;
if (!keyImageKnown) { if (!keyImageKnown) {
Utils::showMessageBox("Unable to sweep output", "Unable to sweep output: key image unknown", true); QMessageBox::warning(this, "Unable to sweep output", "Unable to sweep output: key image unknown");
return; return;
} }
@@ -194,6 +209,7 @@ void CoinsWidget::onSweepOutput() {
qCritical() << "key image: " << keyImage; qCritical() << "key image: " << keyImage;
emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs()); emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs());
dialog->deleteLater();
} }
void CoinsWidget::copy(copyField field) { void CoinsWidget::copy(copyField field) {
@@ -215,6 +231,9 @@ void CoinsWidget::copy(copyField field) {
case Address: case Address:
data = c.address(); data = c.address();
break; break;
case Label:
data = c.addressLabel();
break;
case Height: case Height:
data = QString::number(c.blockHeight()); data = QString::number(c.blockHeight());
break; break;
+2
View File
@@ -48,6 +48,7 @@ private:
KeyImage, KeyImage,
TxID, TxID,
Address, Address,
Label,
Height, Height,
Amount Amount
}; };
@@ -67,6 +68,7 @@ private:
Coins *m_coins; Coins *m_coins;
CoinsModel * m_model; CoinsModel * m_model;
CoinsProxyModel * m_proxyModel; CoinsProxyModel * m_proxyModel;
AppContext *m_ctx;
void showContextMenu(const QPoint & point); void showContextMenu(const QPoint & point);
void copy(copyField field); void copy(copyField field);
+1 -3
View File
@@ -68,9 +68,7 @@ HelpLabel::HelpLabel(QWidget *parent) : QLabel(parent)
void HelpLabel::mouseReleaseEvent(QMouseEvent *event) void HelpLabel::mouseReleaseEvent(QMouseEvent *event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
QMessageBox msgBox(QApplication::activeWindow()); QMessageBox::information(this, "Help", this->help_text);
msgBox.setText(this->help_text);
msgBox.exec();
} }
void HelpLabel::enterEvent(QEvent *event) void HelpLabel::enterEvent(QEvent *event)
+1 -1
View File
@@ -53,7 +53,7 @@
<item> <item>
<widget class="QPlainTextEdit" name="copyrightText"> <widget class="QPlainTextEdit" name="copyrightText">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
+67
View File
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "broadcasttxdialog.h"
#include "ui_broadcasttxdialog.h"
#include "utils/nodes.h"
#include <QMessageBox>
BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx, const QString &transactionHex)
: QDialog(parent)
, m_ctx(ctx)
, ui(new Ui::BroadcastTxDialog)
{
ui->setupUi(this);
m_network = new UtilsNetworking(m_ctx->network, this);
auto node = ctx->nodes->connection();
m_rpc = new DaemonRpc(this, m_network, node.full);
connect(ui->btn_Broadcast, &QPushButton::clicked, this, &BroadcastTxDialog::broadcastTx);
connect(ui->btn_Close, &QPushButton::clicked, this, &BroadcastTxDialog::reject);
connect(m_rpc, &DaemonRpc::ApiResponse, this, &BroadcastTxDialog::onApiResponse);
if (!transactionHex.isEmpty()) {
ui->transaction->setPlainText(transactionHex);
}
this->adjustSize();
}
void BroadcastTxDialog::broadcastTx() {
QString tx = ui->transaction->toPlainText();
QString node = [this]{
QString node;
if (ui->radio_useCustom->isChecked())
node = ui->customNode->text();
else if (ui->radio_useDefault->isChecked())
node = m_ctx->nodes->connection().full;
if (!node.startsWith("http://"))
node = QString("http://%1").arg(node);
return node;
}();
m_rpc->setDaemonAddress(node);
m_rpc->sendRawTransaction(tx);
}
void BroadcastTxDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
if (!resp.ok) {
QMessageBox::warning(this, "Transaction broadcast", resp.status);
return;
}
if (resp.endpoint == DaemonRpc::Endpoint::SEND_RAW_TRANSACTION) {
QMessageBox::information(this, "Transaction broadcast", "Transaction submitted successfully.\n\n"
"If the transaction belongs to this wallet it may take several minutes before it shows up in the history tab.");
}
}
BroadcastTxDialog::~BroadcastTxDialog() {
delete ui;
}
+35
View File
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_BROADCASTTXDIALOG_H
#define FEATHER_BROADCASTTXDIALOG_H
#include <QDialog>
#include "appcontext.h"
#include "utils/daemonrpc.h"
namespace Ui {
class BroadcastTxDialog;
}
class BroadcastTxDialog : public QDialog
{
Q_OBJECT
public:
explicit BroadcastTxDialog(QWidget *parent, AppContext *ctx, const QString &transactionHex = "");
~BroadcastTxDialog() override;
private slots:
void broadcastTx();
void onApiResponse(const DaemonRpc::DaemonResponse &resp);
private:
Ui::BroadcastTxDialog *ui;
UtilsNetworking *m_network;
AppContext *m_ctx;
DaemonRpc *m_rpc;
};
#endif //FEATHER_BROADCASTTXDIALOG_H
+101
View File
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BroadcastTxDialog</class>
<widget class="QDialog" name="BroadcastTxDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>797</width>
<height>575</height>
</rect>
</property>
<property name="windowTitle">
<string>Broadcast transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Transaction:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="transaction">
<property name="minimumSize">
<size>
<width>500</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>Paste hex encoded signed tx string here</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Node</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="radio_useDefault">
<property name="text">
<string>Use currently connected node</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radio_useCustom">
<property name="text">
<string>Use custom node</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="customNode"/>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_Broadcast">
<property name="text">
<string>Broadcast</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_Close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+40 -18
View File
@@ -12,15 +12,34 @@
DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent) DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::DebugInfoDialog) , ui(new Ui::DebugInfoDialog)
, m_ctx(ctx)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->btn_Copy, &QPushButton::clicked, this, &DebugInfoDialog::copyToClipboad);
m_updateTimer.start(5000);
connect(&m_updateTimer, &QTimer::timeout, this, &DebugInfoDialog::updateInfo);
this->updateInfo();
this->adjustSize();
}
void DebugInfoDialog::updateInfo() {
QString torStatus; QString torStatus;
if(ctx->isTorSocks)
// Special case for Tails because we know the status of the daemon by polling tails-tor-has-bootstrapped.target
if(m_ctx->isTails) {
if(m_ctx->tor->torConnected)
torStatus = "Connected";
else
torStatus = "Disconnected";
}
else if(m_ctx->isTorSocks)
torStatus = "Torsocks"; torStatus = "Torsocks";
else if(ctx->tor->localTor) else if(m_ctx->tor->localTor)
torStatus = "Local (assumed to be running)"; torStatus = "Local (assumed to be running)";
else if(ctx->tor->torConnected) else if(m_ctx->tor->torConnected)
torStatus = "Running"; torStatus = "Running";
else else
torStatus = "Unknown"; torStatus = "Unknown";
@@ -28,27 +47,28 @@ DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent)
ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_BRANCH)); ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_BRANCH));
ui->label_moneroVersion->setText(QString("%1-%2").arg(MONERO_VERSION, MONERO_BRANCH)); ui->label_moneroVersion->setText(QString("%1-%2").arg(MONERO_VERSION, MONERO_BRANCH));
ui->label_walletHeight->setText(QString::number(ctx->currentWallet->blockChainHeight())); ui->label_walletHeight->setText(QString::number(m_ctx->currentWallet->blockChainHeight()));
ui->label_daemonHeight->setText(QString::number(ctx->currentWallet->daemonBlockChainHeight())); ui->label_daemonHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainHeight()));
ui->label_restoreHeight->setText(QString::number(ctx->currentWallet->getWalletCreationHeight())); ui->label_targetHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainTargetHeight()));
ui->label_synchronized->setText(ctx->currentWallet->synchronized() ? "True" : "False"); ui->label_restoreHeight->setText(QString::number(m_ctx->currentWallet->getWalletCreationHeight()));
ui->label_synchronized->setText(m_ctx->currentWallet->synchronized() ? "True" : "False");
auto node = ctx->nodes->connection(); auto node = m_ctx->nodes->connection();
ui->label_remoteNode->setText(node.full); ui->label_remoteNode->setText(node.full);
ui->label_walletStatus->setText(this->statusToString(ctx->currentWallet->connected())); ui->label_walletStatus->setText(this->statusToString(m_ctx->currentWallet->connectionStatus()));
ui->label_torStatus->setText(torStatus); ui->label_torStatus->setText(torStatus);
ui->label_websocketStatus->setText(Utils::QtEnumToString(ctx->ws->webSocket.state())); ui->label_websocketStatus->setText(Utils::QtEnumToString(m_ctx->ws->webSocket.state()));
ui->label_netType->setText(Utils::QtEnumToString(ctx->currentWallet->nettype())); ui->label_netType->setText(Utils::QtEnumToString(m_ctx->currentWallet->nettype()));
ui->label_seedType->setText(ctx->currentWallet->getCacheAttribute("feather.seed").isEmpty() ? "25 word" : "14 word"); ui->label_seedType->setText(m_ctx->currentWallet->getCacheAttribute("feather.seed").isEmpty() ? "25 word" : "14 word");
ui->label_viewOnly->setText(ctx->currentWallet->viewOnly() ? "True" : "False"); ui->label_viewOnly->setText(m_ctx->currentWallet->viewOnly() ? "True" : "False");
ui->label_OS->setText(QSysInfo::prettyProductName()); QString os = QSysInfo::prettyProductName();
if (m_ctx->isTails) {
os = QString("Tails %1").arg(TailsOS::version());
}
ui->label_OS->setText(os);
ui->label_timestamp->setText(QString::number(QDateTime::currentSecsSinceEpoch())); ui->label_timestamp->setText(QString::number(QDateTime::currentSecsSinceEpoch()));
connect(ui->btn_Copy, &QPushButton::clicked, this, &DebugInfoDialog::copyToClipboad);
this->adjustSize();
} }
QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) { QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
@@ -67,12 +87,14 @@ QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
} }
void DebugInfoDialog::copyToClipboad() { void DebugInfoDialog::copyToClipboad() {
// Two spaces at the end of each line are for newlines in Markdown
QString text = ""; QString text = "";
text += QString("Feather version: %1 \n").arg(ui->label_featherVersion->text()); text += QString("Feather version: %1 \n").arg(ui->label_featherVersion->text());
text += QString("Monero version: %1 \n").arg(ui->label_moneroVersion->text()); text += QString("Monero version: %1 \n").arg(ui->label_moneroVersion->text());
text += QString("Wallet height: %1 \n").arg(ui->label_walletHeight->text()); text += QString("Wallet height: %1 \n").arg(ui->label_walletHeight->text());
text += QString("Daemon height: %1 \n").arg(ui->label_daemonHeight->text()); text += QString("Daemon height: %1 \n").arg(ui->label_daemonHeight->text());
text += QString("Target height: %1 \n").arg(ui->label_targetHeight->text());
text += QString("Restore height: %1 \n").arg(ui->label_restoreHeight->text()); text += QString("Restore height: %1 \n").arg(ui->label_restoreHeight->text());
text += QString("Synchronized: %1 \n").arg(ui->label_synchronized->text()); text += QString("Synchronized: %1 \n").arg(ui->label_synchronized->text());
+4
View File
@@ -23,6 +23,10 @@ public:
private: private:
QString statusToString(Wallet::ConnectionStatus status); QString statusToString(Wallet::ConnectionStatus status);
void copyToClipboad(); void copyToClipboad();
void updateInfo();
QTimer m_updateTimer;
AppContext *m_ctx;
Ui::DebugInfoDialog *ui; Ui::DebugInfoDialog *ui;
}; };
+46 -26
View File
@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>693</width> <width>693</width>
<height>580</height> <height>612</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -91,14 +91,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="6" column="0">
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Restore height:</string> <string>Restore height:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="6" column="1">
<widget class="QLabel" name="label_restoreHeight"> <widget class="QLabel" name="label_restoreHeight">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -108,14 +108,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
<string>Synchronized:</string> <string>Synchronized:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="7" column="1">
<widget class="QLabel" name="label_synchronized"> <widget class="QLabel" name="label_synchronized">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -125,21 +125,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="8" column="1">
<widget class="Line" name="line_2"> <widget class="Line" name="line_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="9" column="0">
<widget class="QLabel" name="label_27"> <widget class="QLabel" name="label_27">
<property name="text"> <property name="text">
<string>Remote node:</string> <string>Remote node:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="9" column="1">
<widget class="QLabel" name="label_remoteNode"> <widget class="QLabel" name="label_remoteNode">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -149,14 +149,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="10" column="0">
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_17">
<property name="text"> <property name="text">
<string>Wallet status:</string> <string>Wallet status:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="1"> <item row="10" column="1">
<widget class="QLabel" name="label_walletStatus"> <widget class="QLabel" name="label_walletStatus">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -166,14 +166,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="11" column="0">
<widget class="QLabel" name="label_18"> <widget class="QLabel" name="label_18">
<property name="text"> <property name="text">
<string>Tor status:</string> <string>Tor status:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="11" column="1">
<widget class="QLabel" name="label_torStatus"> <widget class="QLabel" name="label_torStatus">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -183,14 +183,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0"> <item row="12" column="0">
<widget class="QLabel" name="label_19"> <widget class="QLabel" name="label_19">
<property name="text"> <property name="text">
<string>Websocket status:</string> <string>Websocket status:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="1"> <item row="12" column="1">
<widget class="QLabel" name="label_websocketStatus"> <widget class="QLabel" name="label_websocketStatus">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -200,21 +200,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="1"> <item row="13" column="1">
<widget class="Line" name="line_3"> <widget class="Line" name="line_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="0"> <item row="14" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Network type:</string> <string>Network type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="1"> <item row="14" column="1">
<widget class="QLabel" name="label_netType"> <widget class="QLabel" name="label_netType">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -224,14 +224,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="0"> <item row="15" column="0">
<widget class="QLabel" name="label_23"> <widget class="QLabel" name="label_23">
<property name="text"> <property name="text">
<string>Seed type:</string> <string>Seed type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="1"> <item row="15" column="1">
<widget class="QLabel" name="label_seedType"> <widget class="QLabel" name="label_seedType">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -241,14 +241,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="0"> <item row="16" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>View only:</string> <string>View only:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="1"> <item row="16" column="1">
<widget class="QLabel" name="label_viewOnly"> <widget class="QLabel" name="label_viewOnly">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -258,14 +258,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="0"> <item row="19" column="0">
<widget class="QLabel" name="label_24"> <widget class="QLabel" name="label_24">
<property name="text"> <property name="text">
<string>Timestamp:</string> <string>Timestamp:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="1"> <item row="19" column="1">
<widget class="QLabel" name="label_timestamp"> <widget class="QLabel" name="label_timestamp">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -275,27 +275,47 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="17" column="0"> <item row="18" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Operating system:</string> <string>Operating system:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="17" column="1"> <item row="18" column="1">
<widget class="QLabel" name="label_OS"> <widget class="QLabel" name="label_OS">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget> </widget>
</item> </item>
<item row="16" column="1"> <item row="17" column="1">
<widget class="Line" name="line_4"> <widget class="Line" name="line_4">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Target height:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_targetHeight">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
+46 -11
View File
@@ -5,17 +5,39 @@
#include "ui_passwordchangedialog.h" #include "ui_passwordchangedialog.h"
#include <QPushButton> #include <QPushButton>
#include <QMessageBox>
PasswordChangeDialog::PasswordChangeDialog(QWidget *parent) PasswordChangeDialog::PasswordChangeDialog(QWidget *parent, Wallet *wallet)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::PasswordChangeDialog) , ui(new Ui::PasswordChangeDialog)
, m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->icon->setPixmap(QPixmap(":/assets/images/lock.png").scaledToWidth(32, Qt::SmoothTransformation));
bool noPassword = wallet->getPassword().isEmpty();
QString warning_str = noPassword ? "Your wallet is not password protected. Use this dialog to add a password to your wallet." :
"Your wallet is password protected and encrypted. Use this dialog to change your password.";
ui->label_warning->setText(warning_str);
QPixmap pixmap = noPassword ? QPixmap(":/assets/images/unlock.png") : QPixmap(":/assets/images/lock.png");
ui->icon->setPixmap(pixmap.scaledToWidth(32, Qt::SmoothTransformation));
if (noPassword) {
ui->label_currentPassword->hide();
ui->lineEdit_currentPassword->hide();
}
connect(ui->lineEdit_newPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch); connect(ui->lineEdit_newPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch);
connect(ui->lineEdit_confirmPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch); connect(ui->lineEdit_confirmPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch);
connect(ui->btn_Cancel, &QPushButton::clicked, [this]{
this->reject();
});
connect(ui->btn_OK, &QPushButton::clicked, this, &PasswordChangeDialog::setPassword);
ui->label_match->setVisible(false);
this->adjustSize(); this->adjustSize();
} }
@@ -24,15 +46,28 @@ PasswordChangeDialog::~PasswordChangeDialog()
delete ui; delete ui;
} }
QString PasswordChangeDialog::getCurrentPassword() {
return ui->lineEdit_currentPassword->text();
}
QString PasswordChangeDialog::getNewPassword() {
return ui->lineEdit_newPassword->text();
}
void PasswordChangeDialog::passwordsMatch() { void PasswordChangeDialog::passwordsMatch() {
bool match = ui->lineEdit_newPassword->text() == ui->lineEdit_confirmPassword->text(); bool match = ui->lineEdit_newPassword->text() == ui->lineEdit_confirmPassword->text();
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(match); ui->btn_OK->setEnabled(match);
ui->label_match->setHidden(match);
}
void PasswordChangeDialog::setPassword() {
QString currentPassword = ui->lineEdit_currentPassword->text();
QString newPassword = ui->lineEdit_newPassword->text();
if (currentPassword != m_wallet->getPassword()) {
QMessageBox::warning(this, "Error", "Incorrect password");
ui->lineEdit_currentPassword->setText("");
ui->lineEdit_currentPassword->setFocus();
return;
}
if (m_wallet->setPassword(newPassword)) {
QMessageBox::information(this, "Information", "Password changed successfully");
this->accept();
}
else {
QMessageBox::warning(this, "Error", QString("Error: %1").arg(m_wallet->errorString()));
}
} }
+4 -4
View File
@@ -5,6 +5,7 @@
#define FEATHER_PASSWORDCHANGEDIALOG_H #define FEATHER_PASSWORDCHANGEDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class PasswordChangeDialog; class PasswordChangeDialog;
@@ -15,16 +16,15 @@ class PasswordChangeDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit PasswordChangeDialog(QWidget *parent = nullptr); explicit PasswordChangeDialog(QWidget *parent, Wallet *wallet);
~PasswordChangeDialog() override; ~PasswordChangeDialog() override;
QString getCurrentPassword();
QString getNewPassword();
private: private:
Ui::PasswordChangeDialog *ui; Ui::PasswordChangeDialog *ui;
Wallet *m_wallet;
void passwordsMatch(); void passwordsMatch();
void setPassword();
}; };
#endif //FEATHER_PASSWORDCHANGEDIALOG_H #endif //FEATHER_PASSWORDCHANGEDIALOG_H
+55 -41
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>500</width> <width>556</width>
<height>237</height> <height>309</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@@ -30,7 +30,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_warning">
<property name="text"> <property name="text">
<string>Your wallet is password protected and encrypted. Use this dialog to change your password.</string> <string>Your wallet is password protected and encrypted. Use this dialog to change your password.</string>
</property> </property>
@@ -41,6 +41,22 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="0"> <item row="1" column="0">
@@ -65,7 +81,7 @@
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_currentPassword">
<property name="text"> <property name="text">
<string>Current Password:</string> <string>Current Password:</string>
</property> </property>
@@ -88,15 +104,46 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QDialogButtonBox" name="buttonBox"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_match">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Passwords do not match</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="sizeHint" stdset="0">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_Cancel">
<property name="text">
<string>Cancel</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="btn_OK">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>
@@ -105,38 +152,5 @@
<tabstop>lineEdit_confirmPassword</tabstop> <tabstop>lineEdit_confirmPassword</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections/>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PasswordChangeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PasswordChangeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui> </ui>
+26
View File
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "passworddialog.h"
#include "ui_passworddialog.h"
PasswordDialog::PasswordDialog(QWidget *parent, const QString &walletName, bool incorrectPassword)
: QDialog(parent)
, ui(new Ui::PasswordDialog)
{
ui->setupUi(this);
ui->label_wallet->setText(QString("Please enter password for wallet: %1").arg(walletName));
ui->label_incorrectPassword->setVisible(incorrectPassword);
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this]{
password = ui->line_password->text();
});
this->adjustSize();
}
PasswordDialog::~PasswordDialog()
{
delete ui;
}
+27
View File
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_PASSWORDDIALOG_H
#define FEATHER_PASSWORDDIALOG_H
#include <QDialog>
namespace Ui {
class PasswordDialog;
}
class PasswordDialog : public QDialog
{
Q_OBJECT
public:
explicit PasswordDialog(QWidget *parent, const QString &walletName, bool incorrectPassword);
~PasswordDialog() override;
QString password = "";
private:
Ui::PasswordDialog *ui;
};
#endif //FEATHER_PASSWORDDIALOG_H
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PasswordDialog</class>
<widget class="QDialog" name="PasswordDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>832</width>
<height>158</height>
</rect>
</property>
<property name="windowTitle">
<string>Password required</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_wallet">
<property name="text">
<string>Please enter password for wallet: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_incorrectPassword">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; color:#a40000;&quot;&gt;Incorrect password, try again.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PasswordDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PasswordDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+7 -4
View File
@@ -9,15 +9,14 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &title) QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::QrCodeDialog) , ui(new Ui::QrCodeDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
this->setWindowTitle(title); this->setWindowTitle(title);
m_qrc = new QrCode(text, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH); m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
m_pixmap = m_qrc->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
ui->QrCode->setPixmap(m_pixmap); ui->QrCode->setPixmap(m_pixmap);
connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage); connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage);
@@ -32,7 +31,11 @@ QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &
QrCodeDialog::~QrCodeDialog() QrCodeDialog::~QrCodeDialog()
{ {
delete ui; delete ui;
delete m_qrc; }
void QrCodeDialog::setQrCode(const QrCode &qrCode) {
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
ui->QrCode->setPixmap(m_pixmap);
} }
void QrCodeDialog::copyImage() { void QrCodeDialog::copyImage() {
+2 -2
View File
@@ -16,15 +16,15 @@ class QrCodeDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit QrCodeDialog(QWidget *parent, const QString &text, const QString &title = "Qr Code"); explicit QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title = "Qr Code");
~QrCodeDialog() override; ~QrCodeDialog() override;
void setQrCode(const QrCode &qrCode);
private: private:
void copyImage(); void copyImage();
void saveImage(); void saveImage();
Ui::QrCodeDialog *ui; Ui::QrCodeDialog *ui;
QrCode *m_qrc;
QPixmap m_pixmap; QPixmap m_pixmap;
}; };
+27 -3
View File
@@ -4,12 +4,38 @@
#include "ui_seeddialog.h" #include "ui_seeddialog.h"
#include "seeddialog.h" #include "seeddialog.h"
SeedDialog::SeedDialog(const QString &seed, QWidget *parent) SeedDialog::SeedDialog(Wallet *wallet, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::SeedDialog) , ui(new Ui::SeedDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->label_seedIcon->setPixmap(QPixmap(":/assets/images/seed.png").scaledToWidth(64, Qt::SmoothTransformation)); ui->label_seedIcon->setPixmap(QPixmap(":/assets/images/seed.png").scaledToWidth(64, Qt::SmoothTransformation));
ui->label_restoreHeight->setText(QString::number(wallet->getWalletCreationHeight()));
QString seed_14_words = wallet->getCacheAttribute("feather.seed");
QString seed_25_words = wallet->getSeed();
if (seed_14_words.isEmpty()) {
ui->check_toggleSeedType->hide();
this->setSeed(seed_25_words);
} else {
this->setSeed(seed_14_words);
ui->frameRestoreHeight->setVisible(false);
}
connect(ui->check_toggleSeedType, &QCheckBox::toggled, [this, seed_25_words, seed_14_words](bool toggled){
this->setSeed(toggled ? seed_25_words : seed_14_words);
ui->frameRestoreHeight->setVisible(toggled);
});
ui->label_restoreHeightHelp->setHelpText("Should you restore your wallet in the future, "
"specifying this block number will recover your wallet quicker.");
this->adjustSize();
}
void SeedDialog::setSeed(const QString &seed) {
ui->seed->setPlainText(seed); ui->seed->setPlainText(seed);
int words = seed.split(" ").size(); int words = seed.split(" ").size();
@@ -23,8 +49,6 @@ SeedDialog::SeedDialog(const QString &seed, QWidget *parent)
"<li>Never type it on a website</li>" "<li>Never type it on a website</li>"
"<li>Do not store it electronically</li>" "<li>Do not store it electronically</li>"
"</ul>").arg(words)); "</ul>").arg(words));
this->adjustSize();
} }
SeedDialog::~SeedDialog() SeedDialog::~SeedDialog()
+4 -1
View File
@@ -5,6 +5,7 @@
#define FEATHER_SEEDDIALOG_H #define FEATHER_SEEDDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class SeedDialog; class SeedDialog;
@@ -15,10 +16,12 @@ class SeedDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit SeedDialog(const QString& seed, QWidget *parent = nullptr); explicit SeedDialog(Wallet *wallet, QWidget *parent = nullptr);
~SeedDialog() override; ~SeedDialog() override;
private: private:
void setSeed(const QString &seed);
Ui::SeedDialog *ui; Ui::SeedDialog *ui;
}; };
+91 -3
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>542</width> <width>519</width>
<height>244</height> <height>330</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -33,6 +33,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QPlainTextEdit" name="seed"> <widget class="QPlainTextEdit" name="seed">
<property name="enabled"> <property name="enabled">
@@ -44,10 +46,16 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
<height>125</height> <height>300</height>
</size> </size>
</property> </property>
<property name="readOnly"> <property name="readOnly">
@@ -55,18 +63,91 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QFrame" name="frameRestoreHeight">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="HelpLabel" name="label_restoreHeightHelp">
<property name="text">
<string>Restore height:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_restoreHeight">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="check_toggleSeedType">
<property name="text">
<string>Show 25 word seed</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="label_warning"> <widget class="QLabel" name="label_warning">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>warning</string> <string>warning</string>
</property> </property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="orientation">
@@ -79,6 +160,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>HelpLabel</class>
<extends>QLabel</extends>
<header>components.h</header>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections> <connections>
<connection> <connection>
+24 -7
View File
@@ -6,22 +6,37 @@
#include "libwalletqt/CoinsInfo.h" #include "libwalletqt/CoinsInfo.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include <QDebug> #include "utils.h"
TransactionInfoDialog::TransactionInfoDialog(Coins *coins, TransactionInfo *txInfo, QWidget *parent) #include <QMessageBox>
TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::TransactionInfoDialog) , ui(new Ui::TransactionInfoDialog)
, m_coins(coins) , m_wallet(wallet)
, m_txInfo(txInfo) , m_txInfo(txInfo)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->txid->setText(QString(txInfo->hash())); m_txProofWidget = new TxProofWidget(this, wallet, txInfo);
ui->txid->setCursorPosition(0);
ui->label_txid->setText(QString(txInfo->hash()));
if (txInfo->direction() == TransactionInfo::Direction_In) {
ui->txKey->hide();
} else {
QString txKey = m_wallet->getTxKey(txInfo->hash());
txKey = txKey.isEmpty() ? "unknown" : txKey;
ui->label_txKey->setText(txKey);
}
QString blockHeight = QString::number(txInfo->blockHeight());
if (blockHeight == "0")
blockHeight = "Unconfirmed";
ui->label_status->setText(QString("Status: %1 confirmations").arg(txInfo->confirmations())); ui->label_status->setText(QString("Status: %1 confirmations").arg(txInfo->confirmations()));
ui->label_date->setText(QString("Date: %1").arg(txInfo->timestamp().toString("yyyy-MM-dd HH:mm"))); ui->label_date->setText(QString("Date: %1").arg(txInfo->timestamp().toString("yyyy-MM-dd HH:mm")));
ui->label_blockHeight->setText(QString("Block height: %1").arg(txInfo->blockHeight())); ui->label_blockHeight->setText(QString("Block height: %1").arg(blockHeight));
QString direction = txInfo->direction() == TransactionInfo::Direction_In ? "received" : "sent"; QString direction = txInfo->direction() == TransactionInfo::Direction_In ? "received" : "sent";
ui->label_amount->setText(QString("Amount %1: %2").arg(direction, txInfo->displayAmount())); ui->label_amount->setText(QString("Amount %1: %2").arg(direction, txInfo->displayAmount()));
@@ -30,7 +45,7 @@ TransactionInfoDialog::TransactionInfoDialog(Coins *coins, TransactionInfo *txIn
ui->label_fee->setText(QString("Fee: %1").arg(txInfo->isCoinbase() ? WalletManager::displayAmount(0) : fee)); ui->label_fee->setText(QString("Fee: %1").arg(txInfo->isCoinbase() ? WalletManager::displayAmount(0) : fee));
ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(txInfo->unlockTime())); ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(txInfo->unlockTime()));
qDebug() << m_coins->coins_from_txid(txInfo->hash()); qDebug() << m_wallet->coins()->coins_from_txid(txInfo->hash());
QString destinations = txInfo->destinations_formatted(); QString destinations = txInfo->destinations_formatted();
if (destinations.isEmpty()) { if (destinations.isEmpty()) {
@@ -41,6 +56,8 @@ TransactionInfoDialog::TransactionInfoDialog(Coins *coins, TransactionInfo *txIn
ui->destinations->setText(destinations); ui->destinations->setText(destinations);
} }
ui->txProofWidget->addWidget(m_txProofWidget);
this->adjustSize(); this->adjustSize();
} }
+5 -2
View File
@@ -8,6 +8,8 @@
#include <QtSvg/QSvgWidget> #include <QtSvg/QSvgWidget>
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/TransactionInfo.h" #include "libwalletqt/TransactionInfo.h"
#include "libwalletqt/Wallet.h"
#include "widgets/txproofwidget.h"
namespace Ui { namespace Ui {
class TransactionInfoDialog; class TransactionInfoDialog;
@@ -18,14 +20,15 @@ class TransactionInfoDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TransactionInfoDialog(Coins *coins, TransactionInfo *txInfo, QWidget *parent = nullptr); explicit TransactionInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent = nullptr);
~TransactionInfoDialog() override; ~TransactionInfoDialog() override;
private: private:
Ui::TransactionInfoDialog *ui; Ui::TransactionInfoDialog *ui;
TransactionInfo *m_txInfo; TransactionInfo *m_txInfo;
Coins *m_coins; Wallet *m_wallet;
TxProofWidget *m_txProofWidget;
}; };
#endif //FEATHER_TRANSACTIONINFODIALOG_H #endif //FEATHER_TRANSACTIONINFODIALOG_H
+40 -21
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>547</width> <width>829</width>
<height>332</height> <height>570</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -15,34 +15,43 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QGroupBox" name="groupBox">
<property name="text"> <property name="title">
<string>Transaction ID:</string> <string>Transaction ID:</string>
</property> </property>
</widget> <layout class="QVBoxLayout" name="verticalLayout">
</item>
<item> <item>
<widget class="QLineEdit" name="txid"> <widget class="QLabel" name="label_txid">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>525</width>
<height>0</height>
</size>
</property>
<property name="text"> <property name="text">
<string>txid</string> <string>txid</string>
</property> </property>
<property name="readOnly"> <property name="textInteractionFlags">
<bool>true</bool> <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="txKey">
<property name="title">
<string>Transaction key:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_txKey">
<property name="text">
<string>txKey</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@@ -149,6 +158,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="txProofWidget"/>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
+186
View File
@@ -0,0 +1,186 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "txconfadvdialog.h"
#include "ui_txconfadvdialog.h"
#include "libwalletqt/WalletManager.h"
#include "qrcode/QrCode.h"
#include "dialog/qrcodedialog.h"
#include "utils/utils.h"
#include "libwalletqt/PendingTransactionInfo.h"
#include "libwalletqt/Transfer.h"
#include "libwalletqt/Input.h"
#include "model/ModelUtils.h"
#include <QFileDialog>
#include <QMessageBox>
TxConfAdvDialog::TxConfAdvDialog(AppContext *ctx, const QString &description, QWidget *parent)
: QDialog(parent)
, ui(new Ui::TxConfAdvDialog)
, m_ctx(ctx)
, m_exportUnsignedMenu(new QMenu(this))
, m_exportSignedMenu(new QMenu(this))
{
ui->setupUi(this);
m_exportUnsignedMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::unsignedCopy);
m_exportUnsignedMenu->addAction("Show as QR code", this, &TxConfAdvDialog::unsignedQrCode);
m_exportUnsignedMenu->addAction("Save to file", this, &TxConfAdvDialog::unsignedSaveFile);
ui->btn_exportUnsigned->setMenu(m_exportUnsignedMenu);
m_exportSignedMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::signedCopy);
m_exportSignedMenu->addAction("Save to file", this, &TxConfAdvDialog::signedSaveFile);
ui->btn_exportSigned->setMenu(m_exportSignedMenu);
if (m_ctx->currentWallet->viewOnly()) {
ui->btn_exportSigned->hide();
ui->btn_send->hide();
}
ui->label_description->setText(QString("Description: %1").arg(description));
connect(ui->btn_sign, &QPushButton::clicked, this, &TxConfAdvDialog::signTransaction);
connect(ui->btn_send, &QPushButton::clicked, this, &TxConfAdvDialog::broadcastTransaction);
connect(ui->btn_close, &QPushButton::clicked, this, &TxConfAdvDialog::closeDialog);
ui->inputs->setFont(ModelUtils::getMonospaceFont());
ui->outputs->setFont(ModelUtils::getMonospaceFont());
this->adjustSize();
}
void TxConfAdvDialog::setTransaction(PendingTransaction *tx) {
ui->btn_sign->hide();
m_tx = tx;
m_tx->refresh();
PendingTransactionInfo *ptx = m_tx->transaction(0);
ui->txid->setText(tx->txid().first());
ui->amount->setText(WalletManager::displayAmount(tx->amount()));
ui->fee->setText(WalletManager::displayAmount(ptx->fee()));
ui->total->setText(WalletManager::displayAmount(tx->amount() + ptx->fee()));
auto size_str = [this]{
if (m_ctx->currentWallet->viewOnly()) {
return QString("Size: %1 bytes (unsigned)").arg(QString::number(m_tx->unsignedTxToBin().size()));
} else {
auto size = m_tx->signedTxToHex(0).size() / 2;
return QString("Size: %1 bytes (%2 bytes unsigned)").arg(QString::number(size), QString::number(m_tx->unsignedTxToBin().size()));
}
}();
ui->label_size->setText(size_str);
this->setupConstructionData(ptx);
}
void TxConfAdvDialog::setUnsignedTransaction(UnsignedTransaction *utx) {
m_utx = utx;
m_utx->refresh();
ui->btn_exportUnsigned->hide();
ui->btn_exportSigned->hide();
ui->btn_sign->show();
ui->btn_send->hide();
ui->txid->setText("n/a");
ui->label_size->setText("Size: n/a");
ui->amount->setText(WalletManager::displayAmount(utx->amount(0)));
ui->fee->setText(WalletManager::displayAmount(utx->fee(0)));
ui->total->setText(WalletManager::displayAmount(utx->amount(0) + utx->fee(0)));
ConstructionInfo *ci = m_utx->constructionInfo(0);
this->setupConstructionData(ci);
}
void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
QString inputs_str;
auto inputs = ci->inputs();
for (const auto& i: inputs) {
inputs_str += QString("%1 %2\n").arg(i->pubKey(), WalletManager::displayAmount(i->amount()));
}
ui->inputs->setText(inputs_str);
ui->label_inputs->setText(QString("Inputs (%1)").arg(QString::number(inputs.size())));
QString outputs_str;
auto outputs = ci->outputs();
for (const auto& o: outputs) {
outputs_str += QString("%1 %2\n").arg(o->address(), WalletManager::displayAmount(o->amount()));
}
ui->outputs->setText(outputs_str);
ui->label_outputs->setText(QString("Outputs (%1)").arg(QString::number(outputs.size())));
ui->label_ringSize->setText(QString("Ring size: %1").arg(QString::number(ci->minMixinCount() + 1)));
ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(QString::number(ci->unlockTime())));
}
void TxConfAdvDialog::signTransaction() {
QString defaultName = QString("%1_signed_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
QString fn = QFileDialog::getSaveFileName(this, "Save signed transaction to file", QDir::home().filePath(defaultName), "Transaction (*signed_monero_tx)");
if(fn.isEmpty()) return;
m_utx->sign(fn) ? QMessageBox::information(this, "Sign transaction", "Transaction saved successfully")
: QMessageBox::warning(this, "Sign transaction", "Failes to save transaction to file.");
}
void TxConfAdvDialog::unsignedSaveFile() {
QString defaultName = QString("%1_unsigned_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
QString fn = QFileDialog::getSaveFileName(this, "Save transaction to file", QDir::home().filePath(defaultName), "Transaction (*unsigned_monero_tx)");
if(fn.isEmpty()) return;
m_tx->saveToFile(fn) ? QMessageBox::information(this, "Transaction saved to file", "Transaction saved successfully")
: QMessageBox::warning(this, "Save transaction", "Failed to save transaction to file.");
}
void TxConfAdvDialog::signedSaveFile() {
QString defaultName = QString("%1_signed_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
QString fn = QFileDialog::getSaveFileName(this, "Save transaction to file", QDir::home().filePath(defaultName), "Transaction (*signed_monero_tx)");
if(fn.isEmpty()) return;
m_tx->saveToFile(fn) ? QMessageBox::information(this, "Transaction saved to file", "Transaction saved successfully")
: QMessageBox::warning(this, "Save transaction", "Failed to save transaction to file.");
}
void TxConfAdvDialog::unsignedQrCode() {
if (m_tx->unsignedTxToBin().size() > 2953) {
QMessageBox::warning(this, "Unable to show QR code", "Transaction size exceeds the maximum size for QR codes (2953 bytes).");
return;
}
QrCode qr(m_tx->unsignedTxToBin(), QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::LOW);
auto *dialog = new QrCodeDialog(this, qr, "Unsigned Transaction");
dialog->exec();
dialog->deleteLater();
}
void TxConfAdvDialog::unsignedCopy() {
Utils::copyToClipboard(m_tx->unsignedTxToBase64());
}
void TxConfAdvDialog::signedCopy() {
Utils::copyToClipboard(m_tx->signedTxToHex(0));
}
void TxConfAdvDialog::signedQrCode() {
}
void TxConfAdvDialog::broadcastTransaction() {
if (m_tx == nullptr) return;
m_ctx->currentWallet->commitTransactionAsync(m_tx);
QDialog::accept();
}
void TxConfAdvDialog::closeDialog() {
if (m_tx != nullptr)
m_ctx->currentWallet->disposeTransaction(m_tx);
if (m_utx != nullptr)
m_ctx->currentWallet->disposeTransaction(m_utx);
QDialog::reject();
}
TxConfAdvDialog::~TxConfAdvDialog() {
delete ui;
}
+54
View File
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_TXCONFADVDIALOG_H
#define FEATHER_TXCONFADVDIALOG_H
#include <QDialog>
#include <QStandardItemModel>
#include <QAbstractButton>
#include <QMenu>
#include "libwalletqt/PendingTransaction.h"
#include "appcontext.h"
namespace Ui {
class TxConfAdvDialog;
}
class TxConfAdvDialog : public QDialog
{
Q_OBJECT
public:
explicit TxConfAdvDialog(AppContext *ctx, const QString &description, QWidget *parent = nullptr);
~TxConfAdvDialog() override;
void setTransaction(PendingTransaction *tx);
void setUnsignedTransaction(UnsignedTransaction *utx);
private:
void setupConstructionData(ConstructionInfo *ci);
void signTransaction();
void broadcastTransaction();
void closeDialog();
void unsignedCopy();
void unsignedQrCode();
void unsignedSaveFile();
void signedCopy();
void signedQrCode();
void signedSaveFile();
Ui::TxConfAdvDialog *ui;
AppContext *m_ctx;
PendingTransaction *m_tx = nullptr;
UnsignedTransaction *m_utx = nullptr;
QMenu *m_exportUnsignedMenu;
QMenu *m_exportSignedMenu;
};
#endif //FEATHER_TXCONFADVDIALOG_H
+279
View File
@@ -0,0 +1,279 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TxConfAdvDialog</class>
<widget class="QDialog" name="TxConfAdvDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>542</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Transaction ID:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="txid">
<property name="text">
<string>txid</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_amount">
<property name="text">
<string>Amount: </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="amount">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_fee">
<property name="text">
<string>Fee: </string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="fee">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Total:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="total">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_description">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_size">
<property name="text">
<string>Size: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_unlockTime">
<property name="text">
<string>Unlock time: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_ringSize">
<property name="text">
<string>Ringsize:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_inputs">
<property name="text">
<string>Inputs</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="inputs">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_outputs">
<property name="text">
<string>Outputs</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="outputs">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="btn_exportUnsigned">
<property name="text">
<string>Export unsigned</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btn_exportSigned">
<property name="text">
<string>Export signed</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_sign">
<property name="text">
<string>Sign</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_send">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+15 -23
View File
@@ -6,12 +6,16 @@
#include "appcontext.h" #include "appcontext.h"
#include "utils/config.h" #include "utils/config.h"
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "libwalletqt/WalletManager.h"
#include "txconfadvdialog.h"
#include "globals.h"
#include <QMessageBox> #include <QMessageBox>
TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent) TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::TxConfDialog) , ui(new Ui::TxConfDialog)
, m_ctx(ctx)
, m_tx(tx) , m_tx(tx)
, m_address(address) , m_address(address)
, m_description(description) , m_description(description)
@@ -28,44 +32,32 @@ TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const
}; };
QString amount = WalletManager::displayAmount(tx->amount()); QString amount = WalletManager::displayAmount(tx->amount());
QString amount_fiat = convert(tx->amount() / AppContext::cdiv); QString amount_fiat = convert(tx->amount() / globals::cdiv);
ui->label_amount->setText(QString("%1 (%2 %3)").arg(amount, amount_fiat, preferredCur)); ui->label_amount->setText(QString("%1 (%2 %3)").arg(amount, amount_fiat, preferredCur));
QString fee = WalletManager::displayAmount(tx->fee()); QString fee = WalletManager::displayAmount(tx->fee());
QString fee_fiat = convert(tx->fee() / AppContext::cdiv); QString fee_fiat = convert(tx->fee() / globals::cdiv);
ui->label_fee->setText(QString("%1 (%2 %3)").arg(fee, fee_fiat, preferredCur)); ui->label_fee->setText(QString("%1 (%2 %3)").arg(fee, fee_fiat, preferredCur));
QString total = WalletManager::displayAmount(tx->amount() + tx->fee()); QString total = WalletManager::displayAmount(tx->amount() + tx->fee());
QString total_fiat = convert((tx->amount() + tx->fee()) / AppContext::cdiv); QString total_fiat = convert((tx->amount() + tx->fee()) / globals::cdiv);
ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur)); ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur));
ui->label_address->setText(ModelUtils::displayAddress(address, 2)); ui->label_address->setText(ModelUtils::displayAddress(address, 2));
ui->label_address->setFont(ModelUtils::getMonospaceFont()); ui->label_address->setFont(ModelUtils::getMonospaceFont());
ui->label_address->setToolTip(address); ui->label_address->setToolTip(address);
connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::showAdvanced); ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Send");
connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::setShowAdvanced);
AppContext::txCache[tx->txid()[0]] = tx->signedTxToHex(0);
this->adjustSize(); this->adjustSize();
} }
void TxConfDialog::showAdvanced() { void TxConfDialog::setShowAdvanced() {
const auto amount = m_tx->amount() / AppContext::cdiv; this->showAdvanced = true;
const auto fee = m_tx->fee() / AppContext::cdiv; QDialog::reject();
QString body = QString("Address: %2\n").arg(m_address.left(60));
body += m_address.mid(60) + "\n";
if(!m_description.isEmpty())
body = QString("%1Description: %2\n").arg(body, m_description);
body = QString("%1Amount: %2 XMR\n").arg(body, QString::number(amount));
body = QString("%1Fee: %2 XMR\n").arg(body, QString::number(fee));
body = QString("%1Ringsize: %2").arg(body, QString::number(m_mixin + 1));
auto subaddrIndices = m_tx->subaddrIndices();
for (int i = 0; i < subaddrIndices.count(); ++i){
body = QString("%1\nSpending address index: %2").arg(body, QString::number(subaddrIndices.at(i).toInt()));
}
QMessageBox::information(this, "Transaction information", body);
} }
TxConfDialog::~TxConfDialog() { TxConfDialog::~TxConfDialog() {
+8 -2
View File
@@ -7,6 +7,7 @@
#include <QDialog> #include <QDialog>
#include "libwalletqt/PendingTransaction.h" #include "libwalletqt/PendingTransaction.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "appcontext.h"
namespace Ui { namespace Ui {
class TxConfDialog; class TxConfDialog;
@@ -17,13 +18,18 @@ class TxConfDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxConfDialog(PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr); explicit TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr);
~TxConfDialog() override; ~TxConfDialog() override;
bool showAdvanced = false;
private: private:
void showAdvanced(); void setShowAdvanced();
void saveToFile();
void copyToClipboard();
Ui::TxConfDialog *ui; Ui::TxConfDialog *ui;
AppContext *m_ctx;
PendingTransaction *m_tx; PendingTransaction *m_tx;
QString m_address; QString m_address;
QString m_description; QString m_description;
+1 -1
View File
@@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>655</width> <width>844</width>
<height>248</height> <height>248</height>
</rect> </rect>
</property> </property>
+102
View File
@@ -0,0 +1,102 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "tximportdialog.h"
#include "ui_tximportdialog.h"
#include <QMessageBox>
TxImportDialog::TxImportDialog(QWidget *parent, AppContext *ctx)
: QDialog(parent)
, m_ctx(ctx)
, m_loadTimer(new QTimer(this))
, ui(new Ui::TxImportDialog)
{
ui->setupUi(this);
ui->resp->hide();
ui->label_loading->hide();
m_network = new UtilsNetworking(m_ctx->network, this);
auto node = ctx->nodes->connection();
m_rpc = new DaemonRpc(this, m_network, node.full);
connect(ui->btn_load, &QPushButton::clicked, this, &TxImportDialog::loadTx);
connect(ui->btn_import, &QPushButton::clicked, this, &TxImportDialog::onImport);
connect(m_rpc, &DaemonRpc::ApiResponse, this, &TxImportDialog::onApiResponse);
connect(m_loadTimer, &QTimer::timeout, [this]{
ui->label_loading->setText(ui->label_loading->text() + ".");
});
this->adjustSize();
}
void TxImportDialog::loadTx() {
QString txid = ui->line_txid->text();
QString node = m_ctx->nodes->connection().full;
if (!node.startsWith("http://"))
node = QString("http://%1").arg(node);
m_rpc->setDaemonAddress(node);
m_rpc->getTransactions(QStringList() << txid, false, true);
ui->label_loading->setText("Loading transaction");
ui->label_loading->setHidden(false);
m_loadTimer->start(1000);
}
void TxImportDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
m_loadTimer->stop();
ui->label_loading->setHidden(true);
if (!resp.ok) {
QMessageBox::warning(this, "Import transaction", resp.status);
return;
}
if (resp.endpoint == DaemonRpc::Endpoint::GET_TRANSACTIONS) {
ui->resp->setVisible(true);
ui->resp->setPlainText(QJsonDocument(resp.obj).toJson(QJsonDocument::Indented));
this->adjustSize();
if (resp.obj.contains("missed_tx")) {
ui->btn_import->setEnabled(false);
QMessageBox::warning(this, "Load transaction", "Transaction could not be found. Make sure the txid is correct, or try connecting to a different node.");
return;
}
QMessageBox::information(this, "Load transaction", "Transaction loaded successfully.\n\nAfter closing this message box click the Import button to import the transaction into your wallet.");
m_transaction = resp.obj;
ui->btn_import->setEnabled(true);
}
}
void TxImportDialog::onImport() {
QJsonObject tx = m_transaction.value("txs").toArray().first().toObject();
QString txid = tx.value("tx_hash").toString();
QVector<quint64> output_indices;
for (const auto &o: tx.value("output_indices").toArray()) {
output_indices.push_back(o.toInt());
}
quint64 height = tx.value("block_height").toInt();
quint64 timestamp = tx.value("block_timestamp").toInt();
bool pool = tx.value("in_pool").toBool();
bool double_spend_seen = tx.value("double_spend_seen").toBool();
if (m_ctx->currentWallet->importTransaction(tx.value("tx_hash").toString(), output_indices, height, timestamp, false, pool, double_spend_seen)) {
QMessageBox::information(this, "Import transaction", "Transaction imported successfully.");
} else {
QMessageBox::warning(this, "Import transaction", "Transaction import failed.");
}
m_ctx->refreshModels();
}
TxImportDialog::~TxImportDialog() {
delete ui;
}
+39
View File
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_TXIMPORTDIALOG_H
#define FEATHER_TXIMPORTDIALOG_H
#include <QDialog>
#include "appcontext.h"
#include "utils/daemonrpc.h"
namespace Ui {
class TxImportDialog;
}
class TxImportDialog : public QDialog
{
Q_OBJECT
public:
explicit TxImportDialog(QWidget *parent, AppContext *ctx);
~TxImportDialog() override;
private slots:
void loadTx();
void onImport();
void onApiResponse(const DaemonRpc::DaemonResponse &resp);
private:
Ui::TxImportDialog *ui;
UtilsNetworking *m_network;
AppContext *m_ctx;
DaemonRpc *m_rpc;
QTimer *m_loadTimer;
QJsonObject m_transaction;
};
#endif //FEATHER_TXIMPORTDIALOG_H
+115
View File
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TxImportDialog</class>
<widget class="QDialog" name="TxImportDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>442</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>700</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Import Transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="line_txid">
<property name="placeholderText">
<string>Transaction ID</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="resp">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Debug info..</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="btn_load">
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_import">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Import</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_loading">
<property name="text">
<string>Loading transaction</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>TxImportDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TxImportDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+24 -8
View File
@@ -16,26 +16,28 @@ VerifyProofDialog::VerifyProofDialog(Wallet *wallet, QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->btn_verifySpendProof, &QPushButton::clicked, this, &VerifyProofDialog::checkSpendProof); connect(ui->btn_verify, &QPushButton::clicked, this, &VerifyProofDialog::checkProof);
connect(ui->btn_verifyOutProof, &QPushButton::clicked, this, &VerifyProofDialog::checkOutProof);
connect(ui->btn_verifyInProof, &QPushButton::clicked, this, &VerifyProofDialog::checkInProof);
connect(ui->btn_spendClear, &QPushButton::clicked, [this](){ connect(ui->btn_clear, &QPushButton::clicked, [this]{
switch (ui->tabWidget->currentIndex()) {
case 0:
ui->lineEdit_spendTxID->clear(); ui->lineEdit_spendTxID->clear();
ui->lineEdit_spendMessage->clear(); ui->lineEdit_spendMessage->clear();
ui->input_SpendProof->clear(); ui->input_SpendProof->clear();
}); break;
connect(ui->btn_outClear, &QPushButton::clicked, [this](){ case 1:
ui->lineEdit_outTxID->clear(); ui->lineEdit_outTxID->clear();
ui->lineEdit_outAddress->clear(); ui->lineEdit_outAddress->clear();
ui->lineEdit_outMessage->clear(); ui->lineEdit_outMessage->clear();
ui->input_OutProof->clear(); ui->input_OutProof->clear();
}); break;
connect(ui->btn_inClear, &QPushButton::clicked, [this](){ case 2:
ui->lineEdit_inTxID->clear(); ui->lineEdit_inTxID->clear();
ui->lineEdit_inAddress->clear(); ui->lineEdit_inAddress->clear();
ui->lineEdit_inMessage->clear(); ui->lineEdit_inMessage->clear();
ui->input_InProof->clear(); ui->input_InProof->clear();
break;
}
}); });
} }
@@ -44,6 +46,20 @@ VerifyProofDialog::~VerifyProofDialog()
delete ui; delete ui;
} }
void VerifyProofDialog::checkProof() {
switch (ui->tabWidget->currentIndex()) {
case 0:
this->checkSpendProof();
break;
case 1:
this->checkOutProof();
break;
case 2:
this->checkInProof();
break;
}
}
void VerifyProofDialog::checkSpendProof() { void VerifyProofDialog::checkSpendProof() {
auto r = m_wallet->checkSpendProof(ui->lineEdit_spendTxID->text(), ui->lineEdit_spendMessage->text(), ui->input_SpendProof->toPlainText()); auto r = m_wallet->checkSpendProof(ui->lineEdit_spendTxID->text(), ui->lineEdit_spendMessage->text(), ui->input_SpendProof->toPlainText());
+4 -3
View File
@@ -20,12 +20,13 @@ public:
~VerifyProofDialog() override; ~VerifyProofDialog() override;
private slots: private slots:
void checkSpendProof(); void checkProof();
void checkOutProof();
void checkInProof();
private: private:
void checkTxProof(const QString &txId, const QString &address, const QString &message, const QString &signature); void checkTxProof(const QString &txId, const QString &address, const QString &message, const QString &signature);
void checkSpendProof();
void checkOutProof();
void checkInProof();
Ui::VerifyProofDialog *ui; Ui::VerifyProofDialog *ui;
Wallet *m_wallet; Wallet *m_wallet;
+25 -84
View File
@@ -39,17 +39,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Transaction ID:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_spendTxID"/>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
@@ -57,10 +47,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="0" column="1">
<widget class="QLabel" name="label_5"> <widget class="QLineEdit" name="lineEdit_spendTxID"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>SpendProof:</string> <string>Transaction ID:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -71,6 +64,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>SpendProof:</string>
</property>
</widget>
</item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QPlainTextEdit" name="input_SpendProof"> <widget class="QPlainTextEdit" name="input_SpendProof">
<property name="overwriteMode"> <property name="overwriteMode">
@@ -96,37 +96,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_spendClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verifySpendProof">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="OutProof"> <widget class="QWidget" name="OutProof">
@@ -213,37 +182,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_outClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verifyOutProof">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="InProof"> <widget class="QWidget" name="InProof">
@@ -331,10 +269,14 @@
</property> </property>
</spacer> </spacer>
</item> </item>
</layout>
</widget>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<spacer name="horizontalSpacer_3"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@@ -347,27 +289,26 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QPushButton" name="btn_inClear"> <widget class="QPushButton" name="btn_clear">
<property name="text"> <property name="text">
<string>Clear</string> <string>Clear</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="btn_verifyInProof"> <widget class="QPushButton" name="btn_verify">
<property name="text"> <property name="text">
<string>Verify</string> <string>Verify</string>
</property> </property>
<property name="default">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
</layout> </layout>
</widget> </widget>
</widget>
</item>
</layout>
</widget>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>
+59
View File
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include "viewonlydialog.h"
#include "ui_viewonlydialog.h"
ViewOnlyDialog::ViewOnlyDialog(AppContext *ctx, QWidget *parent)
: QDialog(parent)
, ui(new Ui::ViewOnlyDialog), m_ctx(ctx)
{
ui->setupUi(this);
ui->label_restoreHeight->setText(QString::number(ctx->currentWallet->getWalletCreationHeight()));
ui->label_primaryAddress->setText(ctx->currentWallet->address(0, 0));
ui->label_secretViewKey->setText(ctx->currentWallet->getSecretViewKey());
connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboad);
connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet);
ui->btn_Save->setEnabled(!m_ctx->currentWallet->viewOnly());
this->adjustSize();
}
void ViewOnlyDialog::onWriteViewOnlyWallet(){
QString fn = QFileDialog::getSaveFileName(this, "Save .keys wallet file", QDir::homePath(), "Monero wallet (*.keys)");
if(fn.isEmpty()) return;
if(!fn.endsWith(".keys")) fn += ".keys";
QString passwd;
QInputDialog passwordDialog(this);
passwordDialog.setInputMode(QInputDialog::TextInput);
passwordDialog.setTextEchoMode(QLineEdit::Password);
passwordDialog.setWindowTitle("View-Only wallet password");
passwordDialog.setLabelText("Protect this view-only wallet with a password?");
passwordDialog.resize(300, 100);
if((bool)passwordDialog.exec())
passwd = passwordDialog.textValue();
m_ctx->currentWallet->createViewOnly(fn, passwd);
QMessageBox::information(this, "Information", "View-only wallet successfully written to disk.");
}
void ViewOnlyDialog::copyToClipboad() {
QString text = "";
text += QString("Address: %1\n").arg(ui->label_primaryAddress->text());
text += QString("Secret view key: %1\n").arg(ui->label_secretViewKey->text());
text += QString("Restore height: %1\n").arg(ui->label_restoreHeight->text());
Utils::copyToClipboard(text);
}
ViewOnlyDialog::~ViewOnlyDialog()
{
delete ui;
}
+32
View File
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_VIEWONLYDIALOG_H
#define FEATHER_VIEWONLYDIALOG_H
#include <QDialog>
#include "appcontext.h"
namespace Ui {
class ViewOnlyDialog;
}
class ViewOnlyDialog : public QDialog
{
Q_OBJECT
public:
explicit ViewOnlyDialog(AppContext *ctx, QWidget *parent = nullptr);
~ViewOnlyDialog() override;
private slots:
void onWriteViewOnlyWallet();
private:
Ui::ViewOnlyDialog *ui;
AppContext *m_ctx = nullptr;
void copyToClipboad();
};
#endif //FEATHER_KEYSDIALOG_H
+139
View File
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ViewOnlyDialog</class>
<widget class="QDialog" name="ViewOnlyDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>659</width>
<height>254</height>
</rect>
</property>
<property name="windowTitle">
<string>View-Only</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Restore height</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_restoreHeight">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Primary address</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_primaryAddress">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Secret view key</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_secretViewKey">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="btn_Copy">
<property name="text">
<string>Copy</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_Save">
<property name="text">
<string>Create view-only wallet</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ViewOnlyDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ViewOnlyDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+1 -1
View File
@@ -31,7 +31,7 @@ WalletInfoDialog::WalletInfoDialog(AppContext *ctx, QWidget *parent)
void WalletInfoDialog::openWalletDir() { void WalletInfoDialog::openWalletDir() {
QFileInfo file(m_ctx->walletPath); QFileInfo file(m_ctx->walletPath);
QDesktopServices::openUrl(file.absolutePath()); QDesktopServices::openUrl(QUrl(QString("file://%1").arg(file.absolutePath()), QUrl::TolerantMode));
} }
WalletInfoDialog::~WalletInfoDialog() { WalletInfoDialog::~WalletInfoDialog() {
+14
View File
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_GLOBALS_H
#define FEATHER_GLOBALS_H
#include <QtGlobal>
namespace globals
{
const qreal cdiv = 1e12;
}
#endif //FEATHER_GLOBALS_H
+42 -19
View File
@@ -25,15 +25,9 @@ HistoryWidget::HistoryWidget(QWidget *parent)
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);}); m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);}); m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);});
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);}); m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof);
ui->history->setContextMenuPolicy(Qt::CustomContextMenu); ui->history->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){ connect(ui->history, &QTreeView::customContextMenuRequested, this, &HistoryWidget::showContextMenu);
QModelIndex index = ui->history->indexAt(point);
if (index.isValid()) {
m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point));
}
});
connect(ui->search, &QLineEdit::textChanged, this, &HistoryWidget::setSearchFilter); connect(ui->search, &QLineEdit::textChanged, this, &HistoryWidget::setSearchFilter);
connect(ui->history, &QTreeView::doubleClicked, [this](QModelIndex index){ connect(ui->history, &QTreeView::doubleClicked, [this](QModelIndex index){
@@ -45,11 +39,48 @@ HistoryWidget::HistoryWidget(QWidget *parent)
} }
void HistoryWidget::setModel(Coins *coins, TransactionHistoryProxyModel *model, TransactionHistory *txHistory) void HistoryWidget::showContextMenu(const QPoint &point) {
QModelIndex index = ui->history->indexAt(point);
if (!index.isValid()) {
return;
}
QMenu menu(this);
TransactionInfo::Direction direction;
QString txid;
bool unconfirmed;
m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction, &txid, &unconfirmed](TransactionInfo &tInfo) {
direction = tInfo.direction();
txid = tInfo.hash();
unconfirmed = tInfo.isFailed() || tInfo.isPending();
});
if (AppContext::txCache.contains(txid) && unconfirmed) {
menu.addAction(QIcon(":/assets/images/info.png"), "Resend transaction", this, &HistoryWidget::onResendTransaction);
}
menu.addMenu(m_copyMenu);
menu.addAction(QIcon(":/assets/images/info.png"), "Show details", this, &HistoryWidget::showTxDetails);
menu.addAction(QIcon(":/assets/images/network.png"), "View on block explorer", this, &HistoryWidget::onViewOnBlockExplorer);
menu.exec(ui->history->viewport()->mapToGlobal(point));
}
void HistoryWidget::onResendTransaction() {
QModelIndex index = ui->history->currentIndex();
QString txid;
m_txHistory->transaction(m_model->mapToSource(index).row(), [&txid](TransactionInfo &tInfo) {
txid = tInfo.hash();
});
emit resendTransaction(txid);
}
void HistoryWidget::setModel(TransactionHistoryProxyModel *model, Wallet *wallet)
{ {
m_coins = coins;
m_model = model; m_model = model;
m_txHistory = txHistory; m_wallet = wallet;
m_txHistory = m_wallet->history();
ui->history->setModel(m_model); ui->history->setModel(m_model);
ui->history->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->history->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
@@ -66,7 +97,7 @@ void HistoryWidget::showTxDetails() {
}); });
if (i != nullptr) { if (i != nullptr) {
auto * dialog = new TransactionInfoDialog(m_coins, i, this); auto * dialog = new TransactionInfoDialog(m_wallet, i, this);
dialog->exec(); dialog->exec();
} }
} }
@@ -81,14 +112,6 @@ void HistoryWidget::onViewOnBlockExplorer() {
emit viewOnBlockExplorer(txid); emit viewOnBlockExplorer(txid);
} }
void HistoryWidget::getSpendProof() {
QModelIndex index = ui->history->currentIndex();
m_txHistory->transaction(m_model->mapToSource(index).row(), [this](TransactionInfo &tInfo) {
emit spendProof(tInfo.hash());
});
}
void HistoryWidget::setSearchText(const QString &text) { void HistoryWidget::setSearchText(const QString &text) {
ui->search->setText(text); ui->search->setText(text);
} }
+6 -4
View File
@@ -7,6 +7,7 @@
#include "model/TransactionHistoryModel.h" #include "model/TransactionHistoryModel.h"
#include "model/TransactionHistoryProxyModel.h" #include "model/TransactionHistoryProxyModel.h"
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h"
#include <QWidget> #include <QWidget>
#include <QMenu> #include <QMenu>
@@ -21,21 +22,21 @@ Q_OBJECT
public: public:
explicit HistoryWidget(QWidget *parent = nullptr); explicit HistoryWidget(QWidget *parent = nullptr);
void setModel(Coins * coins, TransactionHistoryProxyModel * model, TransactionHistory * txHistory); void setModel(TransactionHistoryProxyModel *model, Wallet *wallet);
~HistoryWidget() override; ~HistoryWidget() override;
public slots: public slots:
void setSearchText(const QString &text); void setSearchText(const QString &text);
signals: signals:
void spendProof(QString txid);
void viewOnBlockExplorer(QString txid); void viewOnBlockExplorer(QString txid);
void resendTransaction(QString txid);
private slots: private slots:
void showTxDetails(); void showTxDetails();
void onViewOnBlockExplorer(); void onViewOnBlockExplorer();
void getSpendProof();
void setSearchFilter(const QString &filter); void setSearchFilter(const QString &filter);
void onResendTransaction();
private: private:
enum copyField { enum copyField {
@@ -45,13 +46,14 @@ private:
}; };
void copy(copyField field); void copy(copyField field);
void showContextMenu(const QPoint &point);
Ui::HistoryWidget *ui; Ui::HistoryWidget *ui;
QMenu *m_contextMenu; QMenu *m_contextMenu;
QMenu *m_copyMenu; QMenu *m_copyMenu;
TransactionHistory *m_txHistory; TransactionHistory *m_txHistory;
TransactionHistoryProxyModel *m_model; TransactionHistoryProxyModel *m_model;
Coins *m_coins; Wallet *m_wallet = nullptr;
}; };
#endif //FEATHER_HISTORYWIDGET_H #endif //FEATHER_HISTORYWIDGET_H
+4
View File
@@ -76,6 +76,10 @@ QString CoinsInfo::address() const {
} }
QString CoinsInfo::addressLabel() const { QString CoinsInfo::addressLabel() const {
if (m_subaddrIndex == 0) {
return m_coinbase ? "Coinbase" : "Change";
}
return m_addressLabel; return m_addressLabel;
} }
+53
View File
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#include "ConstructionInfo.h"
#include "Input.h"
#include "Transfer.h"
quint64 ConstructionInfo::unlockTime() const {
return m_unlockTime;
}
QSet<quint32> ConstructionInfo::subaddressIndices() const {
return m_subaddressIndices;
}
QVector<QString> ConstructionInfo::subaddresses() const {
return m_subaddresses;
}
quint64 ConstructionInfo::minMixinCount() const {
return m_minMixinCount;
}
QList<Input *> ConstructionInfo::inputs() const {
return m_inputs;
}
QList<Transfer *> ConstructionInfo::outputs() const {
return m_outputs;
}
ConstructionInfo::ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent)
: QObject(parent)
, m_unlockTime(pimpl->unlockTime())
, m_minMixinCount(pimpl->minMixinCount())
{
for (auto const &i : pimpl->inputs())
{
Input *input = new Input(i.amount, QString::fromStdString(i.pubkey), this);
m_inputs.append(input);
}
for (auto const &o : pimpl->outputs())
{
Transfer *output = new Transfer(o.amount, QString::fromStdString(o.address), this);
m_outputs.append(output);
}
for (uint32_t i : pimpl->subaddressIndices())
{
m_subaddressIndices.insert(i);
}
}
+46
View File
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef FEATHER_CONSTRUCTIONINFO_H
#define FEATHER_CONSTRUCTIONINFO_H
#include <wallet/api/wallet2_api.h>
#include <QObject>
#include <QSet>
class Input;
class Transfer;
class ConstructionInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(quint64 unlockTime READ unlockTime)
Q_PROPERTY(QSet<quint32> subaddressIndices READ subaddressIndices)
Q_PROPERTY(QVector<QString> subaddresses READ subaddresses)
Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
Q_PROPERTY(QList<Input*> inputs READ inputs)
Q_PROPERTY(QList<Transfer*> outputs READ outputs)
public:
quint64 unlockTime() const;
QSet<quint32> subaddressIndices() const;
QVector<QString> subaddresses() const;
quint64 minMixinCount() const;
QList<Input*> inputs() const;
QList<Transfer*> outputs() const;
private:
explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent = nullptr);
friend class PendingTransactionInfo;
friend class UnsignedTransaction;
quint64 m_unlockTime;
QSet<quint32> m_subaddressIndices;
QVector<QString> m_subaddresses;
quint64 m_minMixinCount;
mutable QList<Input*> m_inputs;
mutable QList<Transfer*> m_outputs;
};
#endif //FEATHER_CONSTRUCTIONINFO_H
+29
View File
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef FEATHER_INPUT_H
#define FEATHER_INPUT_H
#include <wallet/api/wallet2_api.h>
#include <QObject>
#include <utility>
class Input : public QObject
{
Q_OBJECT
Q_PROPERTY(quint64 amount READ amount)
Q_PROPERTY(QString pubKey READ pubKey)
private:
explicit Input(uint64_t _amount, QString _address, QObject *parent = nullptr): QObject(parent), m_amount(_amount), m_pubkey(std::move(_address)) {};
friend class ConstructionInfo;
quint64 m_amount;
QString m_pubkey;
public:
quint64 amount() const { return m_amount; }
QString pubKey() const { return m_pubkey; }
};
#endif //FEATHER_INPUT_H
+32 -7
View File
@@ -16,10 +16,12 @@ QString PendingTransaction::errorString() const
bool PendingTransaction::commit() bool PendingTransaction::commit()
{ {
// Save transaction to file if fileName is set. return m_pimpl->commit();
if(!m_fileName.isEmpty()) }
return m_pimpl->commit(m_fileName.toStdString());
return m_pimpl->commit(m_fileName.toStdString()); bool PendingTransaction::saveToFile(const QString &fileName)
{
return m_pimpl->commit(fileName.toStdString());
} }
quint64 PendingTransaction::amount() const quint64 PendingTransaction::amount() const
@@ -37,7 +39,6 @@ quint64 PendingTransaction::fee() const
return m_pimpl->fee(); return m_pimpl->fee();
} }
QStringList PendingTransaction::txid() const QStringList PendingTransaction::txid() const
{ {
QStringList list; QStringList list;
@@ -63,9 +64,33 @@ QList<QVariant> PendingTransaction::subaddrIndices() const
return result; return result;
} }
void PendingTransaction::setFilename(const QString &fileName) QByteArray PendingTransaction::unsignedTxToBin() const {
return QByteArray::fromStdString(m_pimpl->unsignedTxToBin());
}
QString PendingTransaction::unsignedTxToBase64() const
{ {
m_fileName = fileName; return QString::fromStdString(m_pimpl->unsignedTxToBase64());
}
QString PendingTransaction::signedTxToHex(int index) const
{
return QString::fromStdString(m_pimpl->signedTxToHex(index));
}
PendingTransactionInfo * PendingTransaction::transaction(int index) const {
return m_pending_tx_info[index];
}
void PendingTransaction::refresh()
{
qDeleteAll(m_pending_tx_info);
m_pending_tx_info.clear();
m_pimpl->refresh();
for (const auto i : m_pimpl->getAll()) {
m_pending_tx_info.append(new PendingTransactionInfo(i, this));
}
} }
PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent) PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent)
+11 -3
View File
@@ -9,6 +9,8 @@
#include <QVariant> #include <QVariant>
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include "PendingTransactionInfo.h"
//namespace Monero { //namespace Monero {
//class PendingTransaction; //class PendingTransaction;
@@ -45,21 +47,27 @@ public:
Status status() const; Status status() const;
QString errorString() const; QString errorString() const;
Q_INVOKABLE bool commit(); Q_INVOKABLE bool commit();
bool saveToFile(const QString &fileName);
quint64 amount() const; quint64 amount() const;
quint64 dust() const; quint64 dust() const;
quint64 fee() const; quint64 fee() const;
QStringList txid() const; QStringList txid() const;
quint64 txCount() const; quint64 txCount() const;
QList<QVariant> subaddrIndices() const; QList<QVariant> subaddrIndices() const;
Q_INVOKABLE void setFilename(const QString &fileName); QByteArray unsignedTxToBin() const;
QString unsignedTxToBase64() const;
QString signedTxToHex(int index) const;
void refresh();
PendingTransactionInfo * transaction(int index) const;
private: private:
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = 0); explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = nullptr);
private: private:
friend class Wallet; friend class Wallet;
Monero::PendingTransaction * m_pimpl; Monero::PendingTransaction * m_pimpl;
QString m_fileName; mutable QList<PendingTransactionInfo*> m_pending_tx_info;
}; };
#endif // PENDINGTRANSACTION_H #endif // PENDINGTRANSACTION_H
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#include "PendingTransactionInfo.h"
#include "Input.h"
#include "Transfer.h"
quint64 PendingTransactionInfo::fee() const {
return m_fee;
}
quint64 PendingTransactionInfo::dust() const {
return m_dust;
}
bool PendingTransactionInfo::dustAddedToFee() const {
return m_dustAddedToFee;
}
QString PendingTransactionInfo::txKey() const {
return m_txKey;
}
PendingTransactionInfo::PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent)
: ConstructionInfo(pimpl->constructionData(), parent)
, m_fee(pimpl->fee())
, m_dust(pimpl->dust())
, m_dustAddedToFee(pimpl->dustAddedToFee())
, m_txKey(QString::fromStdString(pimpl->txKey()))
{
}
+46
View File
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef FEATHER_PENDINGTRANSACTIONINFO_H
#define FEATHER_PENDINGTRANSACTIONINFO_H
#include <wallet/api/wallet2_api.h>
#include "ConstructionInfo.h"
#include <QObject>
#include <QSet>
class Input;
class Transfer;
class PendingTransactionInfo : public ConstructionInfo
{
Q_OBJECT
Q_PROPERTY(quint64 fee READ fee)
Q_PROPERTY(quint64 dust READ dust)
Q_PROPERTY(bool dustAddedToFee READ dustAddedToFee)
Q_PROPERTY(QString txKey READ txKey)
Q_PROPERTY(quint64 unlockTime READ unlockTime)
Q_PROPERTY(QSet<quint32> subaddressIndices READ subaddressIndices)
Q_PROPERTY(QVector<QString> subaddresses READ subaddresses)
Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
Q_PROPERTY(QList<Input*> inputs READ inputs)
Q_PROPERTY(QList<Transfer*> outputs READ outputs)
public:
quint64 fee() const;
quint64 dust() const;
bool dustAddedToFee() const;
QString txKey() const;
private:
explicit PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent = nullptr);
friend class PendingTransaction;
quint64 m_fee;
quint64 m_dust;
bool m_dustAddedToFee;
QString m_txKey;
};
#endif //FEATHER_PENDINGTRANSACTIONINFO_H
+19
View File
@@ -28,6 +28,11 @@ bool TransactionInfo::isCoinbase() const
return m_coinbase; return m_coinbase;
} }
quint64 TransactionInfo::balanceDelta() const
{
return m_amount + m_fee;
}
double TransactionInfo::amount() const double TransactionInfo::amount() const
{ {
// there's no unsigned uint64 for JS, so better use double // there's no unsigned uint64 for JS, so better use double
@@ -44,6 +49,11 @@ QString TransactionInfo::displayAmount() const
return WalletManager::displayAmount(m_amount); return WalletManager::displayAmount(m_amount);
} }
quint64 TransactionInfo::atomicFee() const
{
return m_fee;
}
QString TransactionInfo::fee() const QString TransactionInfo::fee() const
{ {
if(m_fee == 0) if(m_fee == 0)
@@ -127,6 +137,15 @@ QString TransactionInfo::destinations_formatted() const
return destinations; return destinations;
} }
QList<QString> TransactionInfo::destinations() const
{
QList<QString> dests;
for (auto const& t: m_transfers) {
dests.append(t->address());
}
return dests;
}
QString TransactionInfo::rings_formatted() const QString TransactionInfo::rings_formatted() const
{ {
QString rings; QString rings;
+3
View File
@@ -52,10 +52,12 @@ public:
bool isPending() const; bool isPending() const;
bool isFailed() const; bool isFailed() const;
bool isCoinbase() const; bool isCoinbase() const;
quint64 balanceDelta() const;
double amount() const; double amount() const;
quint64 atomicAmount() const; quint64 atomicAmount() const;
QString displayAmount() const; QString displayAmount() const;
QString fee() const; QString fee() const;
quint64 atomicFee() const;
quint64 blockHeight() const; quint64 blockHeight() const;
QString description() const; QString description() const;
QSet<quint32> subaddrIndex() const; QSet<quint32> subaddrIndex() const;
@@ -72,6 +74,7 @@ public:
QString paymentId() const; QString paymentId() const;
//! only applicable for output transactions //! only applicable for output transactions
//! used in tx details popup //! used in tx details popup
QList<QString> destinations() const;
QString destinations_formatted() const; QString destinations_formatted() const;
QString rings_formatted() const; QString rings_formatted() const;
+1
View File
@@ -17,6 +17,7 @@ private:
explicit Transfer(uint64_t _amount, QString _address, QObject *parent = 0): QObject(parent), m_amount(_amount), m_address(std::move(_address)) {}; explicit Transfer(uint64_t _amount, QString _address, QObject *parent = 0): QObject(parent), m_amount(_amount), m_address(std::move(_address)) {};
private: private:
friend class TransactionInfo; friend class TransactionInfo;
friend class ConstructionInfo;
quint64 m_amount; quint64 m_amount;
QString m_address; QString m_address;
public: public:
+15
View File
@@ -83,6 +83,21 @@ void UnsignedTransaction::setFilename(const QString &fileName)
m_fileName = fileName; m_fileName = fileName;
} }
ConstructionInfo * UnsignedTransaction::constructionInfo(int index) const {
return m_construction_info[index];
}
void UnsignedTransaction::refresh()
{
qDeleteAll(m_construction_info);
m_construction_info.clear();
m_pimpl->refresh();
for (const auto i : m_pimpl->getAll()) {
m_construction_info.append(new ConstructionInfo(i, this));
}
}
UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, Monero::Wallet *walletImpl, QObject *parent) UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, Monero::Wallet *walletImpl, QObject *parent)
: QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl) : QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl)
{ {
+6 -3
View File
@@ -7,14 +7,13 @@
#include <QObject> #include <QObject>
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include "libwalletqt/PendingTransactionInfo.h"
class UnsignedTransaction : public QObject class UnsignedTransaction : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QString errorString READ errorString)
// Q_PROPERTY(QList<qulonglong> amount READ amount)
// Q_PROPERTY(QList<qulonglong> fee READ fee)
Q_PROPERTY(quint64 txCount READ txCount) Q_PROPERTY(quint64 txCount READ txCount)
Q_PROPERTY(QString confirmationMessage READ confirmationMessage) Q_PROPERTY(QString confirmationMessage READ confirmationMessage)
Q_PROPERTY(QStringList recipientAddress READ recipientAddress) Q_PROPERTY(QStringList recipientAddress READ recipientAddress)
@@ -41,15 +40,19 @@ public:
quint64 minMixinCount() const; quint64 minMixinCount() const;
Q_INVOKABLE bool sign(const QString &fileName) const; Q_INVOKABLE bool sign(const QString &fileName) const;
Q_INVOKABLE void setFilename(const QString &fileName); Q_INVOKABLE void setFilename(const QString &fileName);
void refresh();
ConstructionInfo * constructionInfo(int index) const;
private: private:
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = 0); explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = nullptr);
~UnsignedTransaction(); ~UnsignedTransaction();
private: private:
friend class Wallet; friend class Wallet;
Monero::UnsignedTransaction * m_pimpl; Monero::UnsignedTransaction * m_pimpl;
QString m_fileName; QString m_fileName;
Monero::Wallet * m_walletImpl; Monero::Wallet * m_walletImpl;
mutable QList<ConstructionInfo*> m_construction_info;
}; };
#endif // UNSIGNEDTRANSACTION_H #endif // UNSIGNEDTRANSACTION_H
+229 -88
View File
@@ -2,6 +2,11 @@
// Copyright (c) 2014-2020, The Monero Project. // Copyright (c) 2014-2020, The Monero Project.
#include "Wallet.h" #include "Wallet.h"
#include <chrono>
#include <stdexcept>
#include <thread>
#include "PendingTransaction.h" #include "PendingTransaction.h"
#include "UnsignedTransaction.h" #include "UnsignedTransaction.h"
#include "TransactionHistory.h" #include "TransactionHistory.h"
@@ -27,6 +32,8 @@
#include <QVector> #include <QVector>
#include <QMutexLocker> #include <QMutexLocker>
#include "utils/ScopeGuard.h"
namespace { namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5; static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30; static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@@ -40,6 +47,11 @@ Wallet::Wallet(QObject * parent)
{ {
} }
Wallet::ConnectionStatus Wallet::connectionStatus() const
{
return m_connectionStatus;
}
QString Wallet::getSeed() const QString Wallet::getSeed() const
{ {
return QString::fromStdString(m_walletImpl->seed()); return QString::fromStdString(m_walletImpl->seed());
@@ -65,41 +77,28 @@ NetworkType::Type Wallet::nettype() const
return static_cast<NetworkType::Type>(m_walletImpl->nettype()); return static_cast<NetworkType::Type>(m_walletImpl->nettype());
} }
void Wallet::updateConnectionStatusAsync()
{
m_scheduler.run([this] {
if (m_connectionStatus == Wallet::ConnectionStatus_Disconnected)
{
setConnectionStatus(ConnectionStatus_Connecting);
}
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
if (newStatus != m_connectionStatus || !m_initialized) {
m_initialized = true;
setConnectionStatus(newStatus);
}
// Release lock
m_connectionStatusRunning = false;
});
}
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
{
// cache connection status
if (forceCheck || !m_initialized || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
m_connectionStatusRunning = true;
m_connectionStatusTime.restart();
updateConnectionStatusAsync();
}
return m_connectionStatus;
}
bool Wallet::disconnected() const bool Wallet::disconnected() const
{ {
return m_disconnected; return m_disconnected;
} }
bool Wallet::refreshing() const
{
return m_refreshing;
}
void Wallet::refreshingSet(bool value)
{
if (m_refreshing.exchange(value) != value)
{
emit refreshingChanged();
}
}
void Wallet::setConnectionTimeout(int timeout) {
m_connectionTimeout = timeout;
}
void Wallet::setConnectionStatus(ConnectionStatus value) void Wallet::setConnectionStatus(ConnectionStatus value)
{ {
if (m_connectionStatus == value) if (m_connectionStatus == value)
@@ -120,6 +119,29 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
} }
} }
QString Wallet::getProxyAddress() const
{
QMutexLocker locker(&m_proxyMutex);
return m_proxyAddress;
}
void Wallet::setProxyAddress(QString address)
{
m_scheduler.run([this, address] {
{
QMutexLocker locker(&m_proxyMutex);
if (!m_walletImpl->setProxy(address.toStdString()))
{
qCritical() << "failed to set proxy" << address;
}
m_proxyAddress = address;
}
emit proxyAddressChanged();
});
}
bool Wallet::synchronized() const bool Wallet::synchronized() const
{ {
return m_walletImpl->synchronized(); return m_walletImpl->synchronized();
@@ -135,6 +157,11 @@ bool Wallet::setPassword(const QString &password)
return m_walletImpl->setPassword(password.toStdString()); return m_walletImpl->setPassword(password.toStdString());
} }
QString Wallet::getPassword()
{
return QString::fromStdString(m_walletImpl->getPassword());
}
QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const
{ {
return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex)); return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex));
@@ -145,20 +172,18 @@ QString Wallet::path() const
return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->path())); return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->path()));
} }
//void Wallet::storeAsync(const QJSValue &callback, const QString &path /* = "" */)
//void Wallet::storeAsync(const QVariant &callback, const QString &path /* = "" */)
//{ //{
// const auto future = m_scheduler.run( // const auto future = m_scheduler.run(
// [this, path] { // [this, path] {
// QMutexLocker locker(&m_storeMutex); // QMutexLocker locker(&m_asyncMutex);
//
// return QVariantList({m_walletImpl->store(path.toStdString())}); // return QJSValueList({m_walletImpl->store(path.toStdString())});
// }, // },
// callback); // callback);
// if (!future.first) // if (!future.first)
// { // {
// QVariant(callback).call(QVariantList({false})); // QJSValue(callback).call(QJSValueList({false}));
// } // }
//} //}
@@ -167,7 +192,7 @@ void Wallet::store(const QString &path)
m_walletImpl->store(path.toStdString()); m_walletImpl->store(path.toStdString());
} }
bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight) bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight, const QString& proxyAddress)
{ {
qDebug() << "init non async"; qDebug() << "init non async";
if (isRecovering){ if (isRecovering){
@@ -181,7 +206,20 @@ bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 uppe
if (isRecovering || isRecoveringFromDevice) { if (isRecovering || isRecoveringFromDevice) {
m_walletImpl->setRefreshFromBlockHeight(restoreHeight); m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
} }
m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
{
QMutexLocker locker(&m_proxyMutex);
if (!m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL, false, proxyAddress.toStdString()))
{
return false;
}
m_proxyAddress = proxyAddress;
}
emit proxyAddressChanged();
setTrustedDaemon(trustedDaemon);
setTrustedDaemon(trustedDaemon); setTrustedDaemon(trustedDaemon);
return true; return true;
} }
@@ -193,17 +231,24 @@ void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemon
m_daemonPassword = daemonPassword; m_daemonPassword = daemonPassword;
} }
void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight) void Wallet::initAsync(
const QString &daemonAddress,
bool trustedDaemon /* = false */,
quint64 upperTransactionLimit /* = 0 */,
bool isRecovering /* = false */,
bool isRecoveringFromDevice /* = false */,
quint64 restoreHeight /* = 0 */,
const QString &proxyAddress /* = "" */)
{ {
qDebug() << "initAsync: " + daemonAddress; qDebug() << "initAsync: " + daemonAddress;
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight] { const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight); bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress);
if (success) if (success)
{ {
emit walletCreationHeightChanged(); emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh"; qDebug() << "init async finished - starting refresh";
connected(true); refreshHeightAsync();
m_walletImpl->startRefresh(); startRefresh();
} }
}); });
if (future.first) if (future.first)
@@ -246,6 +291,11 @@ void Wallet::setTrustedDaemon(bool arg)
m_walletImpl->setTrustedDaemon(arg); m_walletImpl->setTrustedDaemon(arg);
} }
void Wallet::setUseSSL(bool ssl)
{
m_useSSL = ssl;
}
bool Wallet::viewOnly() const bool Wallet::viewOnly() const
{ {
return m_walletImpl->watchOnly(); return m_walletImpl->watchOnly();
@@ -358,6 +408,8 @@ void Wallet::refreshHeightAsync()
daemonHeightFuture.second.waitForFinished(); daemonHeightFuture.second.waitForFinished();
targetHeightFuture.second.waitForFinished(); targetHeightFuture.second.waitForFinished();
setConnectionStatus(ConnectionStatus_Connected);
emit heightRefreshed(walletHeight, daemonHeight, targetHeight); emit heightRefreshed(walletHeight, daemonHeight, targetHeight);
}); });
} }
@@ -372,7 +424,8 @@ quint64 Wallet::daemonBlockChainHeight() const
// cache daemon blockchain height for some time (60 seconds by default) // cache daemon blockchain height for some time (60 seconds by default)
if (m_daemonBlockChainHeight == 0 if (m_daemonBlockChainHeight == 0
|| m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl) { || m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl)
{
m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight(); m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight();
m_daemonBlockChainHeightTime.restart(); m_daemonBlockChainHeightTime.restart();
} }
@@ -382,7 +435,8 @@ quint64 Wallet::daemonBlockChainHeight() const
quint64 Wallet::daemonBlockChainTargetHeight() const quint64 Wallet::daemonBlockChainTargetHeight() const
{ {
if (m_daemonBlockChainTargetHeight <= 1 if (m_daemonBlockChainTargetHeight <= 1
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) { || m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl)
{
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight(); m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
// Target height is set to 0 if daemon is synced. // Target height is set to 0 if daemon is synced.
@@ -396,9 +450,9 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
return m_daemonBlockChainTargetHeight; return m_daemonBlockChainTargetHeight;
} }
bool Wallet::exportKeyImages(const QString& path) bool Wallet::exportKeyImages(const QString& path, bool all)
{ {
return m_walletImpl->exportKeyImages(path.toStdString()); return m_walletImpl->exportKeyImages(path.toStdString(), all);
} }
bool Wallet::importKeyImages(const QString& path) bool Wallet::importKeyImages(const QString& path)
@@ -406,42 +460,40 @@ bool Wallet::importKeyImages(const QString& path)
return m_walletImpl->importKeyImages(path.toStdString()); return m_walletImpl->importKeyImages(path.toStdString());
} }
bool Wallet::refresh() bool Wallet::exportOutputs(const QString& path, bool all) {
{ return m_walletImpl->exportOutputs(path.toStdString(), all);
bool result = m_walletImpl->refresh();
m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
m_coins->refresh(currentSubaddressAccount());
m_subaddressAccount->getAll();
if (result)
emit updated();
return result;
} }
void Wallet::refreshAsync() bool Wallet::importOutputs(const QString& path) {
{ return m_walletImpl->importOutputs(path.toStdString());
qDebug() << "refresh async";
m_walletImpl->refreshAsync();
} }
void Wallet::setAutoRefreshInterval(int seconds) bool Wallet::importTransaction(const QString& txid, const QVector<quint64>& output_indeces, quint64 height, quint64 timestamp, bool miner_tx, bool pool, bool double_spend_seen) {
{ std::vector<uint64_t> o_indeces;
m_walletImpl->setAutoRefreshInterval(seconds); for (const auto &o : output_indeces) {
o_indeces.push_back(o);
} }
int Wallet::autoRefreshInterval() const return m_walletImpl->importTransaction(
{ txid.toStdString(),
return m_walletImpl->autoRefreshInterval(); o_indeces,
height,
17, // todo: get actual block_version
timestamp,
miner_tx,
pool,
double_spend_seen);
} }
void Wallet::startRefresh() const void Wallet::startRefresh()
{ {
m_walletImpl->startRefresh(); m_refreshEnabled = true;
m_refreshNow = true;
} }
void Wallet::pauseRefresh() const void Wallet::pauseRefresh()
{ {
m_walletImpl->pauseRefresh(); m_refreshEnabled = false;
} }
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id, PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -501,7 +553,7 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
{ {
m_scheduler.run([this, key_image, dst_addr, outputs, priority] { m_scheduler.run([this, key_image, dst_addr, outputs, priority] {
PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority); PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority);
emit transactionCreated(tx, dst_addr, "", 0); // todo: return true mixincount emit transactionCreated(tx, dst_addr, "", 10); // todo: return true mixincount
}); });
} }
@@ -528,6 +580,21 @@ UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
return result; return result;
} }
UnsignedTransaction * Wallet::loadTxFromBase64Str(const QString &unsigned_tx)
{
Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTxFromBase64Str(unsigned_tx.toStdString());
UnsignedTransaction * result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
return result;
}
PendingTransaction * Wallet::loadSignedTxFile(const QString &fileName)
{
qDebug() << "Tying to load " << fileName;
Monero::PendingTransaction * ptImpl = m_walletImpl->loadSignedTx(fileName.toStdString());
PendingTransaction * result = new PendingTransaction(ptImpl, this);
return result;
}
bool Wallet::submitTxFile(const QString &fileName) const bool Wallet::submitTxFile(const QString &fileName) const
{ {
qDebug() << "Trying to submit " << fileName; qDebug() << "Trying to submit " << fileName;
@@ -537,6 +604,28 @@ bool Wallet::submitTxFile(const QString &fileName) const
return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages"); return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages");
} }
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
{
refreshingSet(true);
const auto cleanup = sg::make_scope_guard([this]() noexcept {
refreshingSet(false);
});
{
QMutexLocker locker(&m_asyncMutex);
bool result = m_walletImpl->refresh();
if (historyAndSubaddresses)
{
m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
m_subaddressAccount->getAll();
}
return result;
}
}
void Wallet::commitTransactionAsync(PendingTransaction *t) void Wallet::commitTransactionAsync(PendingTransaction *t)
{ {
m_scheduler.run([this, t] { m_scheduler.run([this, t] {
@@ -556,7 +645,6 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
delete t; delete t;
} }
// @ TODO: QJSValue could probably be QVARIANT
//void Wallet::estimateTransactionFeeAsync(const QString &destination, //void Wallet::estimateTransactionFeeAsync(const QString &destination,
// quint64 amount, // quint64 amount,
// PendingTransaction::Priority priority, // PendingTransaction::Priority priority,
@@ -713,12 +801,10 @@ QString Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QSt
return QString::fromStdString(result); return QString::fromStdString(result);
} }
QString Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const TxProof Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const
{ {
std::string result = m_walletImpl->getTxProof(txid.toStdString(), address.toStdString(), message.toStdString()); std::string result = m_walletImpl->getTxProof(txid.toStdString(), address.toStdString(), message.toStdString());
if (result.empty()) return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString()));
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
} }
//void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback) //void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback)
@@ -738,12 +824,10 @@ TxProofResult Wallet::checkTxProof(const QString &txid, const QString &address,
return {success, good, received, in_pool, confirmations}; return {success, good, received, in_pool, confirmations};
} }
Q_INVOKABLE QString Wallet::getSpendProof(const QString &txid, const QString &message) const Q_INVOKABLE TxProof Wallet::getSpendProof(const QString &txid, const QString &message) const
{ {
std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString()); std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString());
if (result.empty()) return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString()));
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
} }
//void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback) //void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback)
@@ -831,7 +915,6 @@ bool Wallet::verifySignedMessage(const QString &message, const QString &address,
return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString()); return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString());
} }
} }
bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error)
{ {
std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error; std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error;
@@ -852,6 +935,8 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
bool Wallet::rescanSpent() bool Wallet::rescanSpent()
{ {
QMutexLocker locker(&m_asyncMutex);
return m_walletImpl->rescanSpent(); return m_walletImpl->rescanSpent();
} }
@@ -992,6 +1077,14 @@ void Wallet::onWalletPassphraseNeeded(bool on_device)
emit this->walletPassphraseNeeded(on_device); emit this->walletPassphraseNeeded(on_device);
} }
quint64 Wallet::getBytesReceived() const {
return m_walletImpl->getBytesReceived();
}
quint64 Wallet::getBytesSent() const {
return m_walletImpl->getBytesSent();
}
void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
{ {
if (m_walletListener != nullptr) if (m_walletListener != nullptr)
@@ -1020,7 +1113,11 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_subaddressAccount(nullptr) , m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr) , m_subaddressAccountModel(nullptr)
, m_coinsModel(nullptr) , m_coinsModel(nullptr)
, m_refreshNow(false)
, m_refreshEnabled(false)
, m_refreshing(false)
, m_scheduler(this) , m_scheduler(this)
, m_useSSL(true)
{ {
m_history = new TransactionHistory(m_walletImpl->history(), this); m_history = new TransactionHistory(m_walletImpl->history(), this);
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this); m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
@@ -1038,11 +1135,16 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false; m_connectionStatusRunning = false;
m_daemonUsername = ""; m_daemonUsername = "";
m_daemonPassword = ""; m_daemonPassword = "";
startRefreshThread();
} }
Wallet::~Wallet() Wallet::~Wallet()
{ {
qDebug() << "~Wallet: Closing wallet"; qDebug("~Wallet: Closing wallet");
pauseRefresh();
m_walletImpl->stop();
m_scheduler.shutdownWaitForFinished(); m_scheduler.shutdownWaitForFinished();
@@ -1062,13 +1164,52 @@ Wallet::~Wallet()
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl); //Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical) if(status() == Status_Critical)
qDebug("Not storing wallet cache"); qDebug("Not storing wallet cache");
else if( m_walletImpl->store("")) // Don't store on wallet close for now
qDebug("Wallet cache stored successfully"); // else if( m_walletImpl->store(""))
else // qDebug("Wallet cache stored successfully");
qDebug("Error storing wallet cache"); // else
// qDebug("Error storing wallet cache");
delete m_walletImpl; delete m_walletImpl;
m_walletImpl = NULL; m_walletImpl = NULL;
delete m_walletListener; delete m_walletListener;
m_walletListener = NULL; m_walletListener = NULL;
qDebug("m_walletImpl deleted"); qDebug("m_walletImpl deleted");
} }
void Wallet::startRefreshThread()
{
const auto future = m_scheduler.run([this] {
constexpr const std::chrono::seconds refreshInterval{10};
constexpr const std::chrono::milliseconds intervalResolution{100};
auto last = std::chrono::steady_clock::now();
while (!m_scheduler.stopping())
{
if (m_refreshEnabled)
{
const auto now = std::chrono::steady_clock::now();
const auto elapsed = now - last;
if (elapsed >= refreshInterval || m_refreshNow)
{
m_refreshNow = false;
refresh(false);
last = std::chrono::steady_clock::now();
}
}
std::this_thread::sleep_for(intervalResolution);
}
});
if (!future.first)
{
throw std::runtime_error("failed to start auto refresh thread");
}
}
void Wallet::onRefreshed(bool success) {
if (success) {
setConnectionStatus(ConnectionStatus_Connected);
} else {
setConnectionStatus(ConnectionStatus_Disconnected);
}
}
+80 -27
View File
@@ -8,7 +8,6 @@
#include <QObject> #include <QObject>
#include <QMutex> #include <QMutex>
#include <QList> #include <QList>
//#include <QJSValue>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here; #include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
@@ -23,11 +22,17 @@ namespace Monero {
struct Wallet; // forward declaration struct Wallet; // forward declaration
} }
struct TxProof {
TxProof(QString proof, QString error = "")
: proof(std::move(proof)), error(std::move(error)){}
QString proof;
QString error;
};
class TransactionHistory; class TransactionHistory;
class TransactionHistoryModel; class TransactionHistoryModel;
class TransactionHistoryProxyModel; class TransactionHistoryProxyModel;
class TransactionHistorySortFilterModel;
class AddressBook; class AddressBook;
class AddressBookModel; class AddressBookModel;
class Subaddress; class Subaddress;
@@ -52,11 +57,12 @@ class Wallet : public QObject, public PassprasePrompter
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged) Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
Q_PROPERTY(QString seed READ getSeed) Q_PROPERTY(QString seed READ getSeed)
Q_PROPERTY(QString seedLanguage READ getSeedLanguage) Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(NetworkType::Type nettype READ nettype) Q_PROPERTY(NetworkType::Type nettype READ nettype)
Q_PROPERTY(ConnectionStatus connected READ connected) Q_PROPERTY(ConnectionStatus connectionStatus READ connectionStatus)
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged) Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged)
Q_PROPERTY(bool synchronized READ synchronized) Q_PROPERTY(bool synchronized READ synchronized)
Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QString errorString READ errorString)
@@ -76,6 +82,7 @@ class Wallet : public QObject, public PassprasePrompter
Q_PROPERTY(QString secretSpendKey READ getSecretSpendKey) Q_PROPERTY(QString secretSpendKey READ getSecretSpendKey)
Q_PROPERTY(QString publicSpendKey READ getPublicSpendKey) Q_PROPERTY(QString publicSpendKey READ getPublicSpendKey)
Q_PROPERTY(QString daemonLogPath READ getDaemonLogPath CONSTANT) Q_PROPERTY(QString daemonLogPath READ getDaemonLogPath CONSTANT)
Q_PROPERTY(QString proxyAddress READ getProxyAddress WRITE setProxyAddress NOTIFY proxyAddressChanged)
Q_PROPERTY(quint64 walletCreationHeight READ getWalletCreationHeight WRITE setWalletCreationHeight NOTIFY walletCreationHeightChanged) Q_PROPERTY(quint64 walletCreationHeight READ getWalletCreationHeight WRITE setWalletCreationHeight NOTIFY walletCreationHeightChanged)
public: public:
@@ -98,6 +105,9 @@ public:
Q_ENUM(ConnectionStatus) Q_ENUM(ConnectionStatus)
//! return connection status
ConnectionStatus connectionStatus() const;
//! returns mnemonic seed //! returns mnemonic seed
QString getSeed() const; QString getSeed() const;
@@ -113,19 +123,19 @@ public:
//! returns network type of the wallet. //! returns network type of the wallet.
NetworkType::Type nettype() const; NetworkType::Type nettype() const;
//! returns whether the wallet is connected, and version status
Q_INVOKABLE ConnectionStatus connected(bool forceCheck = false);
void updateConnectionStatusAsync();
//! returns true if wallet was ever synchronized //! returns true if wallet was ever synchronized
bool synchronized() const; bool synchronized() const;
//! returns last operation's error message //! returns last operation's error message
QString errorString() const; QString errorString() const;
//! changes the password using existing parameters (path, seed, seed lang) //! changes the password using existing parameters (path, seed, seed lang)
Q_INVOKABLE bool setPassword(const QString &password); Q_INVOKABLE bool setPassword(const QString &password);
//! get current wallet password
Q_INVOKABLE QString getPassword();
//! returns wallet's public address //! returns wallet's public address
Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const; Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
@@ -138,7 +148,14 @@ public:
// Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = ""); // Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = "");
//! initializes wallet asynchronously //! initializes wallet asynchronously
Q_INVOKABLE void initAsync(const QString &daemonAddress, bool trustedDaemon = false, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0); Q_INVOKABLE void initAsync(
const QString &daemonAddress,
bool trustedDaemon = false,
quint64 upperTransactionLimit = 0,
bool isRecovering = false,
bool isRecoveringFromDevice = false,
quint64 restoreHeight = 0,
const QString &proxyAddress = "");
// Set daemon rpc user/pass // Set daemon rpc user/pass
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = ""); Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
@@ -149,9 +166,15 @@ public:
//! connects to daemon //! connects to daemon
Q_INVOKABLE bool connectToDaemon(); Q_INVOKABLE bool connectToDaemon();
//! indicates id daemon is trusted //! set connect to daemon timeout
Q_INVOKABLE void setConnectionTimeout(int timeout);
//! indicates if daemon is trusted
Q_INVOKABLE void setTrustedDaemon(bool arg); Q_INVOKABLE void setTrustedDaemon(bool arg);
//! indicates if ssl should be used to connect to daemon
Q_INVOKABLE void setUseSSL(bool ssl);
//! returns balance //! returns balance
Q_INVOKABLE quint64 balance() const; Q_INVOKABLE quint64 balance() const;
Q_INVOKABLE quint64 balance(quint32 accountIndex) const; Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
@@ -184,24 +207,22 @@ public:
Q_INVOKABLE void refreshHeightAsync(); Q_INVOKABLE void refreshHeightAsync();
//! export/import key images //! export/import key images
Q_INVOKABLE bool exportKeyImages(const QString& path); Q_INVOKABLE bool exportKeyImages(const QString& path, bool all = false);
Q_INVOKABLE bool importKeyImages(const QString& path); Q_INVOKABLE bool importKeyImages(const QString& path);
//! export/import outputs
Q_INVOKABLE bool exportOutputs(const QString& path, bool all = false);
Q_INVOKABLE bool importOutputs(const QString& path);
//! import a transaction
Q_INVOKABLE bool importTransaction(const QString& txid, const QVector<quint64>& output_indeces, quint64 height, quint64 timestamp, bool miner_tx, bool pool, bool double_spend_seen);
//! refreshes the wallet //! refreshes the wallet
Q_INVOKABLE bool refresh(); Q_INVOKABLE bool refresh(bool historyAndSubaddresses = false);
//! refreshes the wallet asynchronously
Q_INVOKABLE void refreshAsync();
//! setup auto-refresh interval in seconds
Q_INVOKABLE void setAutoRefreshInterval(int seconds);
//! return auto-refresh interval in seconds
Q_INVOKABLE int autoRefreshInterval() const;
// pause/resume refresh // pause/resume refresh
Q_INVOKABLE void startRefresh() const; Q_INVOKABLE void startRefresh();
Q_INVOKABLE void pauseRefresh() const; Q_INVOKABLE void pauseRefresh();
//! returns current wallet's block height //! returns current wallet's block height
//! (can be less than daemon's blockchain height when wallet sync in progress) //! (can be less than daemon's blockchain height when wallet sync in progress)
@@ -248,6 +269,12 @@ public:
//! Sign a transfer from file //! Sign a transfer from file
Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName); Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName);
//! Load an unsigned transaction from a base64 encoded string
Q_INVOKABLE UnsignedTransaction * loadTxFromBase64Str(const QString &unsigned_tx);
//! Load a signed transaction from file
Q_INVOKABLE PendingTransaction * loadSignedTxFile(const QString &fileName);
//! Submit a transfer from file //! Submit a transfer from file
Q_INVOKABLE bool submitTxFile(const QString &fileName) const; Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
@@ -327,11 +354,11 @@ public:
Q_INVOKABLE QString getTxKey(const QString &txid) const; Q_INVOKABLE QString getTxKey(const QString &txid) const;
//Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &callback); //Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &callback);
Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address); Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const; Q_INVOKABLE TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const;
// Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback); // Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback);
//Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); //Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
Q_INVOKABLE TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); Q_INVOKABLE TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const; Q_INVOKABLE TxProof getSpendProof(const QString &txid, const QString &message) const;
// Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback); // Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback);
Q_INVOKABLE QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const; Q_INVOKABLE QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
// Rescan spent outputs // Rescan spent outputs
@@ -372,6 +399,9 @@ public:
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false); Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
virtual void onWalletPassphraseNeeded(bool on_device) override; virtual void onWalletPassphraseNeeded(bool on_device) override;
Q_INVOKABLE quint64 getBytesReceived() const;
Q_INVOKABLE quint64 getBytesSent() const;
// TODO: setListenter() when it implemented in API // TODO: setListenter() when it implemented in API
signals: signals:
// emitted on every event happened with wallet // emitted on every event happened with wallet
@@ -380,7 +410,7 @@ signals:
// emitted when refresh process finished (could take a long time) // emitted when refresh process finished (could take a long time)
// signalling only after we // signalling only after we
void refreshed(); void refreshed(bool success);
void moneySpent(const QString &txId, quint64 amount); void moneySpent(const QString &txId, quint64 amount);
void moneyReceived(const QString &txId, quint64 amount); void moneyReceived(const QString &txId, quint64 amount);
@@ -402,6 +432,8 @@ signals:
void connectionStatusChanged(int status) const; void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const; void currentSubaddressAccountChanged() const;
void disconnectedChanged() const; void disconnectedChanged() const;
void proxyAddressChanged() const;
void refreshingChanged() const;
private: private:
Wallet(QObject * parent = nullptr); Wallet(QObject * parent = nullptr);
@@ -409,10 +441,24 @@ private:
~Wallet(); ~Wallet();
//! initializes wallet //! initializes wallet
bool init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight); bool init(
const QString &daemonAddress,
bool trustedDaemon,
quint64 upperTransactionLimit,
bool isRecovering,
bool isRecoveringFromDevice,
quint64 restoreHeight,
const QString& proxyAddress);
bool disconnected() const; bool disconnected() const;
bool refreshing() const;
void refreshingSet(bool value);
void onRefreshed(bool success);
void setConnectionStatus(ConnectionStatus value); void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const;
void setProxyAddress(QString address);
void startRefreshThread();
private: private:
friend class WalletManager; friend class WalletManager;
@@ -445,13 +491,20 @@ private:
mutable SubaddressAccountModel * m_subaddressAccountModel; mutable SubaddressAccountModel * m_subaddressAccountModel;
Coins * m_coins; Coins * m_coins;
mutable CoinsModel * m_coinsModel; mutable CoinsModel * m_coinsModel;
QMutex m_asyncMutex;
QMutex m_connectionStatusMutex; QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning; bool m_connectionStatusRunning;
QString m_daemonUsername; QString m_daemonUsername;
QString m_daemonPassword; QString m_daemonPassword;
QString m_proxyAddress;
mutable QMutex m_proxyMutex;
std::atomic<bool> m_refreshNow;
std::atomic<bool> m_refreshEnabled;
std::atomic<bool> m_refreshing;
WalletListenerImpl *m_walletListener; WalletListenerImpl *m_walletListener;
FutureScheduler m_scheduler; FutureScheduler m_scheduler;
QMutex m_storeMutex; int m_connectionTimeout = 30;
bool m_useSSL;
}; };
+3 -2
View File
@@ -41,10 +41,11 @@ void WalletListenerImpl::updated()
} }
// called when wallet refreshed by background thread or explicitly // called when wallet refreshed by background thread or explicitly
void WalletListenerImpl::refreshed() void WalletListenerImpl::refreshed(bool success)
{ {
qDebug() << __FUNCTION__; qDebug() << __FUNCTION__;
emit m_wallet->refreshed(); m_wallet->onRefreshed(success);
emit m_wallet->refreshed(success);
} }
void WalletListenerImpl::onDeviceButtonRequest(uint64_t code) void WalletListenerImpl::onDeviceButtonRequest(uint64_t code)

Some files were not shown because too many files have changed in this diff Show More