Compare commits

..
237 Commits
Author SHA1 Message Date
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
dsc 8c8d6250d9 Merge pull request 'add AUR package file' (#51) from wowario/feather:master into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/51
2020-10-12 14:32:06 +00:00
wowario 657cd6340b add AUR package file 2020-10-12 12:29:08 +03:00
dsc cd1cd5cb75 Merge pull request 'cmake: set CMAKE_SKIP_RPATH on Linux to fix empty RPATH token issue' (#50) from dsc/feather:fix-rpath into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/50
2020-10-11 22:50:51 +00:00
xiphonanddsc 3f50564f11 cmake: set CMAKE_SKIP_RPATH on Linux to fix empty RPATH token issue
https://github.com/monero-project/monero-gui/pull/3150/commits/6ed536982953d870010d8fa065dccbffeb6cae50
https://github.com/monero-project/monero-gui/issues/3142#issuecomment-705940446
2020-10-12 00:48:46 +02:00
dsc 48fb92dc60 Merge pull request 'Windows: no seperators between statusbar widgets' (#48) from tobtoht/feather:windows_status_sep into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/48
2020-10-11 21:37:11 +00:00
tobtoht 5641cf4d9e Windows: no seperators between statusbar widgets 2020-10-11 22:16:33 +02:00
dsc d9eb521e9f Merge pull request 'History, Coins, Xmr.to: double click row to open info dialog' (#49) from tobtoht/feather:history_double_click into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/49
2020-10-11 19:50:59 +00:00
tobtoht 970f8e084d History, Coins, Xmr.to: double click row to open info dialog 2020-10-11 21:49:54 +02:00
dsc bd7ebdf947 Merge pull request 'Windows: hide help button in dialogs' (#47) from tobtoht/feather:window_hide_help into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/47
2020-10-11 18:20:42 +00:00
tobtoht 64da8f217c Windows: hide help button in dialogs 2020-10-11 20:02:23 +02:00
dsc a104a05cfa Merge pull request 'Windows: indent settings file' (#44) from tobtoht/feather:windows_settings_newlines into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/44
2020-10-11 17:51:38 +00:00
dsc 17c1526057 Merge pull request 'Move MainWindow::getContext() to constructor' (#45) from tobtoht/feather:ctx_to_constructor into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/45
2020-10-11 17:23:19 +00:00
tobtoht 2bddad004d Move MainWindow::getContext() to constructor
ctx always exists, spares a few if else statements
2020-10-11 19:16:33 +02:00
dsc 9c139e40d3 Merge pull request 'Xmr.to: disable tor checkbox on Tails and Whonix' (#43) from tobtoht/feather:xmrto_tails_tor into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/43
2020-10-11 17:03:32 +00:00
dsc a12b3e0c77 Merge pull request 'Wizard: misc improvements to create wallet pages' (#42) from tobtoht/feather:wizard_create_fix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/42
2020-10-11 16:57:54 +00:00
tobtoht 2ffd5f234b Windows: indent settings file 2020-10-11 18:52:01 +02:00
tobtoht 89ea34cfb7 Wizard: misc improvements to create wallet pages
Don't focus on Generate button
Replace HTML for PlainTextEdit
Set font using Utils::relativeFont
Change directory button text no longer clips
Wizard Pages are no longer orphans
Vertical spacers no longer take up more room than they need to
GridLayout -> VerticalLayout
2020-10-11 18:41:44 +02:00
tobtoht 892416bc51 Xmr.to: disable tor checkbox on Tails and Whonix 2020-10-11 18:38:33 +02:00
dsc 12940361d8 Merge pull request 'Receive: always copy full address' (#41) from tobtoht/feather:receive_copy into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/41
2020-10-11 15:26:20 +00:00
tobtoht 3df0786fb0 Receive: always copy full address 2020-10-11 17:23:13 +02:00
dsc 3668f0e27e Merge pull request 'Fix restore from seed functionality' (#40) from dsc/feather:fix-restore-seed into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/40
2020-10-11 15:10:13 +00:00
dsc b114ef1710 Fix restore from seed functionality 2020-10-11 17:08:34 +02:00
dsc ad7b278508 Merge pull request 'Qrcode: save to current directory' (#37) from tobtoht/feather:qrcode_path into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/37
2020-10-11 14:19:09 +00:00
tobtoht e362f2b45d Merge pull request 'History: fix fiat conversion' (#36) from tobtoht/feather:history_fiat_fix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/36
2020-10-11 13:03:24 +00:00
tobtoht df93b7672a History: fix fiat conversion 2020-10-11 15:02:02 +02:00
tobtoht 7822992837 Qrcode: save to current directory 2020-10-11 14:44:10 +02:00
tobtoht 3f9080332b Merge pull request 'Prices: add support for AUD' (#35) from tobtoht/feather:cur_aud into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/35
2020-10-11 01:26:25 +00:00
tobtoht db689870f1 Prices: add support for AUD 2020-10-11 03:20:41 +02:00
dsc c3fe46c609 Merge pull request 'signed drone builds' (#33) from dsc/feather:sign-drone-yml into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/33
2020-10-10 17:06:12 +00:00
dsc 4ce0b284a6 signed drone builds 2020-10-10 19:05:19 +02:00
dsc e017f3619a Merge pull request 'fix desktop paths (xdgPaths)' (#20) from dsc/feather:fix-xdg-path into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/20
2020-10-10 16:01:11 +00:00
dsc 3d58f13724 fix desktop paths (xdgPaths) 2020-10-10 18:00:07 +02:00
dsc e001e3120f Merge pull request 'Migrate WS server to a machine that's not a potato' (#18) from dsc/feather:change-ws into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/18
2020-10-10 13:14:45 +00:00
dsc 0ff0fd0a26 Migrate WS server to a machine that's not a potato 2020-10-10 15:13:57 +02:00
dsc 996d9cf9c8 Merge pull request 'Small typo' (#17) from dsc/feather:nodes-warning-grammar into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/17
2020-10-10 02:01:56 +00:00
dsc d4359758be grammar 2020-10-10 04:01:25 +02:00
dsc 8b8ee32214 Merge pull request 'TxConfDialog: make amounts selectable' (#14) from tobtoht/feather:txconf_text into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/14
2020-10-09 22:31:59 +00:00
dsc 423b339ab5 Merge pull request 'Balance: don't use scientific notation' (#13) from tobtoht/feather:balance_display into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/13
2020-10-09 22:31:35 +00:00
tobtoht 3888e121d5 Balance: don't use scientific notation 2020-10-10 00:30:52 +02:00
dsc a0c6a75c09 Merge pull request 'History: change tooltip for failed transactions' (#12) from tobtoht/feather:history_note into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/12
2020-10-09 22:24:30 +00:00
dsc b24b57bd2d Merge pull request 'Embed Tor for static Mac OS builds' (#15) from dsc/feather:include-static-tor-mac-os-buildbot into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/15
2020-10-09 22:23:41 +00:00
dsc 1337c1708d Embed Tor executable for static Mac OS builds 2020-10-10 00:23:44 +02:00
tobtoht a0daadc0cb TxConfDialog: make amounts selectable 2020-10-09 21:46:10 +02:00
tobtoht 36495922a1 History: change tooltip for failed transactions 2020-10-09 21:39:37 +02:00
dsc 18543ad33b Merge pull request 'Update README' (#11) from update-readme into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/11
2020-10-09 18:56:16 +00:00
dsc fc73c5e0aa Update README 2020-10-09 20:55:47 +02:00
dsc f029820a37 Merge pull request 'Set default wallet dir on Windows' (#5) from dsc/feather:fix-walletdir-windows into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/5
2020-10-09 16:59:52 +00:00
dsc b4a5319958 Set default wallet dir on Windows 2020-10-09 18:46:17 +02:00
dsc 1981c8b4d0 Merge pull request 'File->Open is causing problems, debug after alpha release' (#4) from dsc/feather:disable-file-open-wallet into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/4
2020-10-09 16:23:04 +00:00
dsc 9958bb4bf5 File->Open is causing problems, debug after alpha release 2020-10-09 18:15:57 +02:00
dsc 144ad14d84 Merge pull request 'Windows: kill tor on exit' (#1) from tobtoht/feather:windows_tor_fix into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/1
2020-10-09 13:52:58 +00:00
tobtoht bc65a2ab58 Windows: kill tor on exit 2020-10-09 14:28:05 +02:00
dsc 1337baf832 pass STATIC definition for xcb plugin qt import 2020-10-09 02:36:09 +02:00
dsc 1337091a72 OpenSSL + no-asm = bad idea™. 2020-10-08 23:08:54 +02:00
179 changed files with 7121 additions and 1702 deletions
+28 -26
View File
@@ -14,11 +14,10 @@ steps:
commands:
- 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 submodule update --init --depth 50 contrib/tor
- git submodule update --init --depth 50 contrib/torsocks
- git submodule update --init --depth 120 monero
- git submodule update --init --depth 120 --recursive monero
- make -j8 release-static
- git config --global url."http://gitea:3000/".insteadOf https://git.wownero.com/
- git submodule update --init monero
- git submodule update --init --recursive monero
- TOR="/usr/local/tor/bin/tor" XMRIG="/xmrig/xmrig" make -j8 release-static
environment:
OPENSSL_ROOT_DIR: /usr/local/openssl/
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
@@ -30,7 +29,7 @@ steps:
- name: files_linux_release
path: /files
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"
- mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN"
@@ -44,20 +43,22 @@ volumes:
path: /var/drone/ccache_linux_release/
- name: files_linux_release
host:
path: /mnt/storage1/feather_files/files/linux-release/
path: /build/feather_files/files/linux-release/
---
kind: pipeline
type: docker
name: linux-release-appimage
steps:
- name: build
image: feather:appimage
volumes:
- name: files_linux_release
path: /files
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"
- cp /files/$BRANCH/$FN feather.zip
- bash ./contrib/build-appimage.sh
- name: deploy
image: feather:appimage
@@ -71,18 +72,18 @@ steps:
- echo "writing to $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"
volumes:
- name: files_linux_appimage
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
type: docker
name: windows-mxe-release
steps:
- name: build
image: feather:win
@@ -94,11 +95,10 @@ steps:
commands:
- 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 submodule update --init --depth 50 contrib/tor
- git submodule update --init --depth 50 contrib/torsocks
- git submodule update --init --depth 120 monero
- git submodule update --init --depth 120 --recursive monero
- PATH=/mxe/usr/bin/:$PATH make -j8 windows-mxe-release
- git config --global url."http://gitea:3000/".insteadOf https://git.wownero.com/
- git submodule update --init monero
- git submodule update --init --recursive monero
- PATH="/mxe/usr/bin/:$PATH" TOR="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" XMRIG="/xmrig/xmrig.exe" make -j8 windows-mxe-release
environment:
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
- name: deploy
@@ -109,23 +109,21 @@ steps:
- name: files_win_release
path: /files
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"
- mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN"
- 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"
volumes:
- name: ccache_win_release
host:
path: /var/drone/ccache_win_release/
- name: files_win_release
host:
path: /mnt/storage1/feather_files/files/windows-mxe-release/
path: /build/feather_files/files/windows-mxe-release/
---
kind: pipeline
type: docker
name: mac-release
@@ -138,7 +136,6 @@ steps:
path: /files
commands:
- 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"
- scp -P22 administrator@steve.jobs.xmr.pm:feather.zip build/feather.zip
- name: deploy
@@ -147,7 +144,7 @@ steps:
- name: files_mac_release
path: /files
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"
- mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN"
@@ -157,4 +154,9 @@ steps:
volumes:
- name: files_mac_release
host:
path: /mnt/storage1/feather_files/files/mac-release/
path: /build/feather_files/files/mac-release/
---
kind: signature
hmac: f16a0379280e2e89987930d635ec6fb938d67732fdaf4ddc488f2a9db64bda2c
...
+3 -3
View File
@@ -1,9 +1,9 @@
[submodule "monero"]
path = monero
url = https://git.wownero.com/feather/monero.git
[submodule "contrib/torsocks"]
path = contrib/torsocks
url = https://git.torproject.org/torsocks.git
[submodule "contrib/tor"]
path = contrib/tor
url = https://git.torproject.org/tor.git
[submodule "contrib/KDMacTouchBar"]
path = contrib/KDMacTouchBar
url = https://github.com/KDAB/KDMacTouchBar.git
+3 -3
View File
@@ -35,7 +35,7 @@ Note: You only need to build the base image once.
#### 3. Build
```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 /root/feather:/feather -w /feather feather:win /bin/bash -c 'PATH="/mxe/usr/bin/:$PATH" TOR="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" XMRIG="/xmrig/xmrig.exe" make windows-mxe-release -j8'
```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
@@ -68,7 +68,7 @@ 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'
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 'TOR="/usr/local/tor/bin/tor" XMRIG="/xmrig/xmrig" make release-static -j8'
```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
@@ -98,4 +98,4 @@ Build Feather.
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.
+53 -29
View File
@@ -7,11 +7,14 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_REVISION "0")
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
set(VERSION "beta-1")
option(FETCH_DEPS "Download dependencies if they are not found" ON)
option(XMRTO "Include Xmr.To module" ON)
option(BUILD_TOR "Build Tor" OFF)
option(MORPHTOKEN "Include MorphToken module" ON)
option(XMRIG "Path to XMRig binary to embed inside Feather" OFF)
option(TOR "Path to Tor binary to embed inside Feather" OFF)
option(TOR_VERSION "Optional git hash or tag of embedded Tor version" "tor-0.4.3.5")
option(STATIC "Link libraries statically, requires static Qt")
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
option(DONATE_BEG "Prompt donation window every once in a while" ON)
@@ -28,7 +31,7 @@ if(DEBUG)
set(CMAKE_VERBOSE_MAKEFILE ON)
endif()
set(MONERO_HEAD "a1404e92cb439ba0f120e7c4a579ed0b9a0372a4")
set(MONERO_HEAD "1fffb4e27a317cdfaf58c7848c143eb7fc3110d9")
set(BUILD_GUI_DEPS ON)
set(ARCH "x86-64")
set(BUILD_64 ON)
@@ -157,6 +160,11 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
locale)
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)
endif()
find_package(X11 REQUIRED)
message(STATUS "X11_FOUND = ${X11_FOUND}")
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
@@ -169,36 +177,48 @@ if(UNIX AND NOT APPLE)
endif()
endif()
# Tor/torsocks
set(TOR_TAG "tor-0.4.3.5")
set(TOR_DIR "${CMAKE_SOURCE_DIR}/contrib/tor")
if(UNIX AND NOT APPLE)
set(TOR_LIB "libtorsocks.so")
elseif(APPLE)
set(TOR_LIB "libtorsocks.dylib")
endif()
if("$ENV{DRONE}" STREQUAL "true" AND STATIC AND BUILD_TOR)
if("$ENV{DRONE}" STREQUAL "true")
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()
# To build Feather with embedded (and static) Tor, pass CMake -DTOR=/path/to/tor
if(TOR)
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} ${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}")
else()
if(BUILD_TOR)
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")
message(STATUS "Skipping Tor inclusion because -DTOR=Off")
endif()
# To build Feather with embedded (and static) XMRig, pass CMake -DXMRIG=/path/to/xmrig
if(XMRIG)
# on the buildbot XMRig is baked into the image
# - linux: See `Dockerfile`
# - windows: See `Dockerfile_windows`
# - macos: manually downloaded an official release
set(XMRIG_COPY_CMD "cp ${XMRIG} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/xmrig")
message(STATUS "${XMRIG_COPY_CMD}")
execute_process(COMMAND bash -c "${XMRIG_COPY_CMD}" RESULT_VARIABLE ret)
if(ret EQUAL "1")
message(FATAL_ERROR "XMRig copy failure: ${XMRIG_COPY_CMD}")
endif()
message(STATUS "Embedding XMRig binary at ${XMRIG}")
else()
message(STATUS "Skipping XMRig inclusion because -DXMRIG=Off")
endif()
if(MINGW)
@@ -346,4 +366,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_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)
+176 -130
View File
@@ -1,188 +1,214 @@
FROM ubuntu:18.04
FROM ubuntu:16.04
ARG THREADS=1
ARG QT_VERSION=5.15.2
RUN apt clean && apt update
RUN apt install -y gnupg
ENV CFLAGS="-fPIC"
ENV CPPFLAGS="-fPIC"
ENV CXXFLAGS="-fPIC"
ENV SOURCE_DATE_EPOCH=1397818193
COPY utils/pubkeys/kitware.asc /kitware.asc
RUN cat /kitware.asc | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
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
RUN apt-get update
RUN apt-get install -y nano vim ccache software-properties-common
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Amsterdam
RUN apt install -y build-essential nano vim aptitude ccache libusb-1.0-0-dev tzdata
RUN add-apt-repository ppa:git-core/ppa
RUN apt-get update
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 && \
cd xorgproto && \
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./autogen.sh && \
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 && \
git reset --hard 94228cde97d9aecfda04a8e699d462ba2b89e3a0 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
git reset --hard 6398e42131eedddde0d98759067dde933191f049 && \
./autogen.sh && \
make -j$THREADS && \
make -j$THREADS install
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libtool-bin && \
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
cd libxau && \
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 install
make -j$THREADS install && \
rm -rf $(pwd)
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 && \
git reset --hard 8287ebd7b752c33b0cabc4982606fe4831106f7e && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
./autogen.sh --enable-shared --disable-static && \
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 && \
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 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 && \
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 && \
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-image && \
cd libxcb-image && \
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 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 && \
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 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 && \
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 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 && \
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 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 && \
cd libx11 && \
git reset --hard db7cca17ad7807e92a928da9d4c68a00f4836da2 && \
ACLOCAL='aclocal -I /usr/local/share/aclocal/' CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
RUN apt install -y bison && \
git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbcommon && \
cd libxkbcommon && \
git reset --hard c43c3c866eb9d52cd8f61e75cbef1c30d07f3a28 && \
./autogen.sh --prefix=/usr --enable-shared --disable-static --enable-x11 --disable-docs && \
make -j$THREADS && \
make -j$THREADS install
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
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
cd zlib && \
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --static && \
./configure --static && \
make -j$THREADS && \
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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b VER-2-10-2 --depth 1 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 && \
git reset --hard 132f19b779828b194b3fede187cee719785db4d8 && \
./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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
cd libexpat/expat && \
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
./buildconf.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \
./configure --disable-shared --enable-static && \
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 && \
cd fontconfig && \
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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
cd icu/icu4c/source && \
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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y wget && \
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 && \
sha256sum -c hashsum.txt && \
tar -xvzf boost_1_73_0.tar.gz && \
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
tar -xzf boost_1_73_0.tar.gz && \
rm boost_1_73_0.tar.gz && \
cd boost_1_73_0 && \
./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 && \
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" | sha256sum -c && \
tar -xzf openssl-1.1.1g.tar.gz && \
rm openssl-1.1.1g.tar.gz && \
cd openssl-1.1.1g && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./config no-asm 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 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 && \
echo "22b63d7a7a45183865cc4141124f12b673e7a17b1fe2b91e433f6547c5d548c3 qt-everywhere-src-5.15.0.tar.xz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
tar -xf qt-everywhere-src-5.15.0.tar.xz
COPY contrib/Qt5.15_LinuxPatch.json /qt-everywhere-src-5.15.0/qtbase/src/gui/configure.json
RUN apt install -y libgl1-mesa-dev libglib2.0-dev libxkbcommon-dev libxkbcommon-x11-dev
RUN cd /qt-everywhere-src-5.15.0 && \
RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
rm /usr/lib/x86_64-linux-gnu/libX11.a && \
rm /usr/lib/x86_64-linux-gnu/libXext.a && \
rm /usr/lib/x86_64-linux-gnu/libX11-xcb.a && \
git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
cd qt5 && \
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 && \
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\ -lz/ /usr/local/lib/pkgconfig/freetype2.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" \
./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 \
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
-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 qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \
-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 \
-nomake examples -nomake tests -nomake tools
RUN cd /qt-everywhere-src-5.15.0 && \
-nomake examples -nomake tests -nomake tools && \
make -j$THREADS && \
make -j$THREADS install
RUN cd qt-everywhere-src-5.15.0/qttools/src/linguist/lrelease && \
qmake && \
make -j$THREADS install && \
cd qttools/src/linguist/lrelease && \
../../../../qtbase/bin/qmake && \
make -j$THREADS && \
make -j$THREADS install
make -j$THREADS install && \
cd ../../../.. && \
rm -rf $(pwd)
RUN apt install -y libudev-dev && \
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
cd libusb && \
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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
cd hidapi && \
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
./bootstrap && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \
./configure --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libsodium-dev && \
git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \
cd libzmq && \
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
./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 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 && \
cd libgpg-error && \
git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \
./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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git && \
cd libgcrypt && \
git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \
./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 install
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b v3.10.0 --depth 1 https://github.com/protocolbuffers/protobuf && \
cd protobuf && \
git reset --hard 6d4e7fd7966c989e38024a8ea693db83758944f1 && \
./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --enable-static --disable-shared && \
./configure --enable-static --disable-shared && \
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 && \
git reset --hard 59ee597f913fcfda7a010a6e106fbee2595f68e4 && \
cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr . && \
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 && \
cd libevent && \
git reset --hard 5df3037d10556bfcb675bc73e516978b75fc7bc7 && \
mkdir build && cd build && \
cmake -DEVENT_LIBRARY_STATIC=ON -DOPENSSL_ROOT_DIR=/usr/local/openssl -DCMAKE_INSTALL_PREFIX=/usr/local/libevent .. && \
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 && \
git reset --hard 2a8b789ea6f308d081f369d78fa7cfdc9d00bf90 && \
bash autogen.sh && \
LDFLAGS="-L/usr/local/openssl/lib/" LIBS="-lssl -lcrypto -lpthread -ldl" CPPFLAGS="-I/usr/local/openssl/include/" ./configure \
--enable-static-zlib \
@@ -291,17 +336,18 @@ RUN git clone -b tor-0.4.3.5 --depth 1 https://git.torproject.org/tor.git && \
--disable-system-torrc \
--prefix=/usr/local/tor && \
make -j$THREADS && \
make -j$THREADS install
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
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cd monero-seed && \
git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \
make -Cbuild install
make -Cbuild install && \
rm -rf $(pwd)
RUN apt install -y curl && \
curl -LO "https://github.com/xmrig/xmrig/releases/download/v6.3.5/xmrig-6.3.5-linux-static-x64.tar.gz" && \
echo "24d4f07cf5850f00ab513b228f95769a5a5ed68d35808d98f9959b58d97985a0 xmrig-6.3.5-linux-static-x64.tar.gz" | sha256sum -c && \
tar xvf xmrig-6.3.5-linux-static-x64.tar.gz --one-top-level=/xmrig --strip 1
+2 -2
View File
@@ -3,7 +3,7 @@ FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
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 build -trimpath -ldflags="-s -w" github.com/probonopd/go-appimage/src/appimagetool
@@ -15,4 +15,4 @@ RUN cd /usr/bin && \
RUN cd / && \
wget -c https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-x86_64 && \
chmod +x runtime-x86_64
chmod +x runtime-x86_64
+8 -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 && \
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
RUN cd mxe && make -j$THREADS MXE_PLUGIN_DIRS='/mxe/plugins/apps/' MXE_TARGETS='x86_64-w64-mingw32.static' tor
@@ -72,3 +72,10 @@ RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \
make -Cbuild install
RUN apt install -y curl && \
curl -LO "https://github.com/xmrig/xmrig/releases/download/v6.3.5/xmrig-6.3.5-gcc-win64.zip" && \
echo "e45915ada7e6e30f6ab40abf33831056449d5914307d7706bb0ad439b6d64c12 xmrig-6.3.5-gcc-win64.zip" > hashsum.txt && \
sha256sum -c hashsum.txt && \
unzip -q xmrig-6.3.5-gcc-win64.zip -d /xmrig && \
mv /xmrig/xmrig-6.3.5/* /xmrig/
+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:
- `-DXMRTO=OFF` - disable Xmr.To feature
- `-DBUILD_TOR=OFF` - disable embedded Tor
- `-DMORPHTOKEN=OFF` - diable MorphToken feature
- `-DTOR=/path/to/tor` - Embed a Tor executable inside Feather
- `-DXMRIG=/path/to/xmrig` - Embed a XMRig executable inside Feather
- `-DDONATE_BEG=OFF` - disable the dreaded donate requests
And:
+11 -4
View File
@@ -31,6 +31,9 @@ CMAKEFLAGS = \
-DBUILD_64=On \
-DBUILD_TESTS=Off \
-DXMRTO=ON \
-DMORPHTOKEN=ON \
-DXMRIG=Off \
-DTOR=Off \
-DCMAKE_CXX_STANDARD=11 \
-DCMAKE_VERBOSE_MAKEFILE=On \
-DINSTALL_VENDORED_LIBUNBOUND=Off \
@@ -40,29 +43,33 @@ CMAKEFLAGS = \
$(CMAKEFLAGS_EXTRA)
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
release-static: CMAKEFLAGS += -DBUILD_TOR=On
release-static: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
release-static: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
release-static:
cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild
windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-release: CMAKEFLAGS += -DBUILD_TOR=On
windows-mxe-release: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
windows-mxe-release: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
windows-mxe-release:
cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TOR=Off
windows-mxe-debug: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
windows-mxe-debug: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug
windows-mxe-debug:
cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild
mac-release: CMAKEFLAGS += -DSTATIC=Off
mac-release: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
mac-release: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64"
mac-release: CMAKEFLAGS += -DBUILD_TOR=Off
mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
mac-release:
cmake -Bbuild $(CMAKEFLAGS)
+35
View File
@@ -0,0 +1,35 @@
# Maintainer: wowario <wowario[at]protonmail[dot]com>
# Contributor: wowario <wowario[at]protonmail[dot]com>
pkgname='monero-feather-git'
pkgver=0.1.0.925ef5683
pkgrel=1
pkgdesc='a free Monero desktop wallet'
license=('BSD')
arch=('x86_64')
url="https://featherwallet.org"
depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc' 'libgcrypt' 'qrencode' 'libsodium' 'libpgm' 'expat' 'qt5-base' 'qt5-websockets' 'tor')
makedepends=('git' 'cmake' 'boost')
source=("${pkgname}"::"git+https://git.wownero.com/feather/feather")
sha256sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname}"
printf "%s.%s" "$(git describe --tags --abbrev=0)" "$(git rev-parse --short=9 HEAD)"
}
build() {
cd "${srcdir}/${pkgname}"
git submodule update --init --recursive
mkdir -p build
cd build
cmake ..
make
}
package_monero-feather-git() {
install -Dm644 "${srcdir}/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
install -Dm755 "${srcdir}/${pkgname}/build/bin/feather" "${pkgdir}/usr/bin/feather"
}
+1 -1
View File
@@ -2,7 +2,7 @@
[![Build Status](https://build.featherwallet.org/api/badges/feather/feather/status.svg)](https://build.featherwallet.org/feather/feather)
Feather is a free, open-source Monero client for Mac OS and Linux platforms written in C++ with the Qt framework. It is created and maintained by [dsc](dsc@xmr.pm) and [tobtoht](thotbot@protonmail.com).
Feather is a free, open-source Monero client Linux with ports for Mac OS and Windows written in C++ with the Qt framework. It is created and maintained by [dsc](dsc@xmr.pm) and [tobtoht](thotbot@protonmail.com).
## Development resources
* Web: [featherwallet.org](https://featherwallet.org)
-22
View File
@@ -2,33 +2,11 @@
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"
mkdir -p "$APPDIR"
mkdir -p "$APPDIR/usr/share/applications/"
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
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...1fffb4e27a
+40 -13
View File
@@ -42,14 +42,16 @@ file(GLOB SOURCE_FILES
"dialog/*.cpp"
)
if(APPLE AND BUILD_TOR)
set(ASSETS_OS "assets_macos_tor.qrc")
elseif(UNIX AND NOT APPLE AND BUILD_TOR)
set(ASSETS_OS "assets_linux_tor.qrc")
elseif(MINGW AND BUILD_TOR)
set(ASSETS_OS "assets_windows_tor.qrc")
else()
message(STATUS "Building without embedded Tor")
if(TOR)
if(APPLE)
set(ASSETS_TOR "assets_tor_macos.qrc")
else()
set(ASSETS_TOR "assets_tor.qrc")
endif()
endif()
if(XMRIG)
set(ASSETS_XMRIG "assets_mining.qrc")
endif()
set(EXECUTABLE_FLAG)
@@ -74,7 +76,8 @@ endif()
add_executable(feather ${EXECUTABLE_FLAG} main.cpp
${SOURCE_FILES}
${RESOURCES}
${ASSETS_OS}
${ASSETS_TOR}
${ASSETS_XMRIG}
)
# mac os bundle
@@ -122,18 +125,34 @@ if(DONATE_BEG)
target_compile_definitions(feather PRIVATE DONATE_BEG=1)
endif()
if(BUILD_TOR)
target_compile_definitions(feather PRIVATE BUILD_TOR=1)
endif()
if(XMRTO)
target_compile_definitions(feather PRIVATE XMRTO=1)
endif()
if(MORPHTOKEN)
target_compile_definitions(feather PRIVATE HAS_MORPHTOKEN=1)
endif()
if(TOR)
target_compile_definitions(feather PRIVATE HAS_TOR=1)
endif()
if(XMRIG)
target_compile_definitions(feather PRIVATE HAS_XMRIG=1)
endif()
if(HAVE_SYS_PRCTL_H)
target_compile_definitions(feather PRIVATE HAVE_SYS_PRCTL_H=1)
endif()
if(STATIC)
target_compile_definitions(feather PRIVATE STATIC=1)
endif()
if("$ENV{DRONE}" STREQUAL "true")
target_compile_definitions(feather PRIVATE DRONE=1)
endif()
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(feather PRIVATE QT_NO_DEBUG=1)
endif()
@@ -186,6 +205,14 @@ target_link_libraries(feather
${QRENCODE_LIBRARY}
)
if(APPLE)
target_link_libraries(feather
KDMacTouchBar
)
target_include_directories(feather
PUBLIC ../contrib/KDMacTouchBar)
endif()
if(NOT APPLE)
target_link_libraries(feather
Qt5::QSvgIconPlugin
+226
View File
@@ -0,0 +1,226 @@
// 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.";
}
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>1</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>
+114 -52
View File
@@ -9,12 +9,14 @@
#include <QDesktopWidget>
#include "appcontext.h"
#include "globals.h"
#include "utils/tails.h"
#include "utils/whonix.h"
#include "utils/utils.h"
#include "utils/prices.h"
#include "utils/networktype.h"
#include "utils/wsclient.h"
#include "utils/config.h"
// libwalletqt
#include "libwalletqt/WalletManager.h"
@@ -28,7 +30,6 @@
#include "model/SubaddressModel.h"
#include "utils/keysfiles.h"
#include "utils/networktype.h"
#include "utils/config.h"
Prices *AppContext::prices = nullptr;
@@ -82,10 +83,11 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
this->defaultWalletDir = QString("%1/Monero/wallets").arg(this->configRoot);
this->defaultWalletDirRoot = QString("%1/Monero").arg(this->configRoot);
#elif defined(Q_OS_WIN)
// @TODO
this->defaultWalletDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Monero";
this->defaultWalletDirRoot = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
#endif
// Create ~/Monero/wallets if it does not exist yet
// Create wallet dirs
if (!QDir().mkpath(defaultWalletDir))
qCritical() << "Unable to create dir: " << defaultWalletDir;
@@ -111,7 +113,6 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
this->nodes = new Nodes(this, this->networkClearnet);
connect(this, &AppContext::nodeSourceChanged, this->nodes, &Nodes::onNodeSourceChanged);
connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes);
connect(this, &AppContext::walletClosing, this->nodes, &Nodes::onWalletClosing);
// Tor & socks proxy
this->ws = new WSClient(this, m_wsUrl);
@@ -146,10 +147,16 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
AppContext::prices = new Prices();
// xmr.to
#if defined(XMRTO)
#ifdef XMRTO
this->XMRTo = new XmrTo(this);
#endif
// XMRig
#ifdef HAS_XMRIG
this->XMRig = new XmRig(this->configDirectory, this);
this->XMRig->prepare();
#endif
this->walletManager = WalletManager::instance();
QString logPath = QString("%1/daemon.log").arg(configDirectory);
Monero::Utils::onStartup();
@@ -169,10 +176,10 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
}
void AppContext::initTor() {
this->tor = new Tor(this);
this->tor = new Tor(this, this);
this->tor->start();
if (!(isTails || isWhonix)) {
if (!(isWhonix)) {
auto networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort);
this->network->setProxy(*networkProxy);
if (m_wsUrl.host().endsWith(".onion"))
@@ -187,7 +194,7 @@ void AppContext::initWS() {
void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) {
// tx cancelled by user
double amount = tx->amount() / AppContext::cdiv;
double amount = tx->amount() / globals::cdiv;
emit createTransactionCancelled(address, amount);
this->currentWallet->disposeTransaction(tx);
}
@@ -226,8 +233,8 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return;
}
auto balance = this->currentWallet->balance() / AppContext::cdiv;
auto unlocked_balance = this->currentWallet->unlockedBalance() / AppContext::cdiv;
auto balance = this->currentWallet->balance() / globals::cdiv;
auto unlocked_balance = this->currentWallet->unlockedBalance() / globals::cdiv;
if(!all && amount > unlocked_balance) {
emit createTransactionError("Not enough money to spend");
return;
@@ -236,7 +243,7 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return;
}
auto amount_num = static_cast<quint64>(amount * AppContext::cdiv);
auto amount_num = static_cast<quint64>(amount * globals::cdiv);
qDebug() << "creating tx";
if(all || amount == balance)
this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority);
@@ -252,7 +259,6 @@ void AppContext::onCreateTransactionError(const QString &msg) {
}
void AppContext::walletClose(bool emitClosedSignal) {
this->nodes->stopTimer();
if(this->currentWallet == nullptr) return;
emit walletClosing();
//ctx->currentWallet->store(); @TODO: uncomment to store on wallet close
@@ -275,6 +281,10 @@ void AppContext::onOpenWallet(const QString &path, const QString &password){
return;
}
if (password.isEmpty()) {
this->walletPassword = "";
}
config()->set(Config::firstRun, false);
this->walletPath = path;
@@ -309,13 +319,14 @@ void AppContext::onWalletOpened(Wallet *wallet) {
emit walletOpenedError(errMsg);
} else {
this->walletClose(false);
emit walletOpenPasswordNeeded(this->walletPassword.isEmpty());
emit walletOpenPasswordNeeded(!this->walletPassword.isEmpty(), wallet->path());
}
return;
}
this->currentWallet = wallet;
this->walletPath = this->currentWallet->path() + ".keys";
this->walletViewOnly = this->currentWallet->viewOnly();
config()->set(Config::walletPath, this->walletPath);
connect(this->currentWallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent);
@@ -329,9 +340,12 @@ void AppContext::onWalletOpened(Wallet *wallet) {
connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
connect(this->currentWallet, &Wallet::connectionStatusChanged, this, &AppContext::onConnectionStatusChanged);
this->nodes->connectToNode();
emit walletOpened();
connect(this->currentWallet, &Wallet::connectionStatusChanged, [this]{
this->nodes->autoConnect();
});
this->nodes->connectToNode();
this->updateBalance();
#ifdef DONATE_BEG
@@ -340,6 +354,18 @@ void AppContext::onWalletOpened(Wallet *wallet) {
// force trigger preferredFiat signal for history model
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) {
@@ -379,7 +405,11 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
else if(cmd == "nodes") {
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") {
QJsonArray crypto_rates = msg.value("data").toArray();
AppContext::prices->cryptoPricesReceived(crypto_rates);
@@ -433,7 +463,8 @@ void AppContext::onWSNodes(const QJsonArray &nodes) {
auto node = new FeatherNode(
obj.value("address").toString(),
(unsigned int)obj.value("height").toInt(),
obj.value("height").toInt(),
obj.value("target_height").toInt(),
obj.value("online").toBool());
QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node);
l.append(r);
@@ -493,31 +524,17 @@ void AppContext::onWSCCS(const QJsonArray &ccs_data) {
}
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");
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");
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_xmrig = QString("%1%2").arg(dir).arg("xmrig");
QString config_dir_torsocks = QString("%1%2").arg(dir).arg("torsocks");
if(!Utils::dirExists(config_dir_torsocks)) {
qDebug() << QString("Creating directory: %1").arg(config_dir_torsocks);
if (!QDir().mkpath(config_dir_torsocks))
throw std::runtime_error("Could not create directory " + config_dir_torsocks.toStdString());
QStringList createDirs({dir, config_dir_tor, config_dir_tordata, config_dir_xmrig});
for(const auto &d: createDirs) {
if(!Utils::dirExists(d)) {
qDebug() << QString("Creating directory: %1").arg(d);
if (!QDir().mkpath(d))
throw std::runtime_error("Could not create directory " + d.toStdString());
}
}
}
@@ -529,12 +546,54 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
return;
}
if(seed.mnemonicSeed.isEmpty()) {
emit walletCreatedError("Mnemonic seed error. Failed to write wallet.");
return;
}
this->currentWallet = seed.writeWallet(this->walletManager, this->networkType, path, password, this->kdfRounds);
if(this->currentWallet == nullptr) {
emit walletCreatedError("Failed to write wallet");
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->store();
this->walletPassword = password;
@@ -556,7 +615,7 @@ void AppContext::onSetRestoreHeight(unsigned int 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
const auto fn = this->currentWallet->path();
@@ -608,8 +667,9 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
}
void AppContext::donateBeg() {
if(this->networkType != NetworkType::Type::MAINNET)
return;
if(this->currentWallet == nullptr) return;
if(this->networkType != NetworkType::Type::MAINNET) return;
if(this->currentWallet->viewOnly()) return;
auto donationCounter = config()->get(Config::donateBeg).toInt();
if(donationCounter == -1)
@@ -637,19 +697,19 @@ AppContext::~AppContext() {
// ############################################## LIBWALLET QT #########################################################
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);
}
void AppContext::onMoneyReceived(const QString &txId, quint64 amount) {
// 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);
}
void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) {
// 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);
if(this->currentWallet->synchronized()) {
@@ -667,13 +727,15 @@ void AppContext::onWalletUpdate() {
this->storeWallet();
}
void AppContext::onWalletRefreshed() {
void AppContext::onWalletRefreshed(bool success) {
if (!this->refreshed) {
refreshModels();
this->refreshed = true;
this->storeWallet();
}
qDebug() << "Wallet refresh status: " << success;
this->currentWallet->refreshHeightAsync();
}
@@ -690,7 +752,7 @@ void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) {
qDebug() << Q_FUNC_INFO << walletHeight << daemonHeight << targetHeight;
if (!this->currentWallet->connected())
if (this->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected)
return;
if (daemonHeight < targetHeight) {
@@ -736,13 +798,13 @@ void AppContext::storeWallet() {
void AppContext::updateBalance() {
if(!this->currentWallet)
throw std::runtime_error("this should not happen, ever");
return;
AppContext::balance = this->currentWallet->balance() / AppContext::cdiv;
auto balance_str = QString::number(balance);
AppContext::balance = this->currentWallet->balance() / globals::cdiv;
auto balance_str = QString::number(balance, 'f');
double unlocked = this->currentWallet->unlockedBalance() / AppContext::cdiv;
auto unlocked_str = QString::number(unlocked);
double unlocked = this->currentWallet->unlockedBalance() / globals::cdiv;
auto unlocked_str = QString::number(unlocked, 'f');
emit balanceUpdated(balance, unlocked, balance_str, unlocked_str);
}
+12 -4
View File
@@ -14,6 +14,7 @@
#include "utils/networking.h"
#include "utils/tor.h"
#include "utils/xmrto.h"
#include "utils/xmrig.h"
#include "utils/wsclient.h"
#include "utils/txfiathistory.h"
#include "widgets/RedditPost.h"
@@ -56,6 +57,7 @@ public:
QString walletPath;
QString walletPassword = "";
bool walletViewOnly = false;
NetworkType::Type networkType;
QString applicationPath;
@@ -67,7 +69,7 @@ public:
const unsigned int kdfRounds = 1;
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
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 *networkClearnet;
@@ -76,6 +78,7 @@ public:
Tor *tor;
WSClient *ws;
XmrTo *XMRTo;
XmRig *XMRig;
Nodes *nodes;
static Prices *prices;
static WalletKeysFilesModel *wallets;
@@ -89,6 +92,8 @@ public:
WalletManager *walletManager;
Wallet *currentWallet = nullptr;
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 updateBalance();
void initTor();
@@ -98,6 +103,7 @@ public:
void walletClose(bool emitClosedSignal = true);
void storeWallet();
void refreshModels();
void setWindowTitle(bool mining = false);
public slots:
void onOpenWallet(const QString& path, const QString &password);
@@ -120,7 +126,7 @@ private slots:
void onMoneyReceived(const QString &txId, quint64 amount);
void onUnconfirmedMoneyReceived(const QString &txId, quint64 amount);
void onWalletUpdate();
void onWalletRefreshed();
void onWalletRefreshed(bool success);
void onWalletOpened(Wallet *wallet);
void onWalletNewBlock(quint64 blockheight, quint64 targetHeight);
void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight);
@@ -140,7 +146,7 @@ signals:
void walletCreatedError(const QString &msg);
void walletCreated(Wallet *wallet);
void walletOpenedError(QString msg);
void walletOpenPasswordNeeded(bool invalidPassword);
void walletOpenPasswordNeeded(bool invalidPassword, QString path);
void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
void createTransactionError(QString message);
void createTransactionCancelled(QString address, double amount);
@@ -149,6 +155,7 @@ signals:
void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes);
void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries);
void nodeSourceChanged(NodeSource nodeSource);
void XMRigDownloads(const QJsonObject &data);
void setCustomNodes(QList<FeatherNode> nodes);
void ccsEmpty();
void openAliasResolveError(const QString &msg);
@@ -160,13 +167,14 @@ signals:
void initiateTransaction();
void endTransaction();
void walletClosing();
void setTitle(const QString &title); // set window title
private:
void sorry();
const unsigned int m_donationBoundary = 15;
UtilsNetworking *m_utilsNetworkingNodes;
QTimer *m_storeTimer = new QTimer(this);
QUrl m_wsUrl = QUrl(QStringLiteral("ws://6wku2m4zrv6j666crlo7lzofv6ud6enzllyhou3ijeigpukymi37caad.onion/ws"));
QUrl m_wsUrl = QUrl(QStringLiteral("ws://7e6egbawekbkxzkv4244pqeqgoo4axko2imgjbedwnn6s5yb6b7oliqd.onion/ws"));
};
#endif //FEATHER_APPCONTEXT_H
+8
View File
@@ -23,6 +23,7 @@
<file>assets/images/coldcard.png</file>
<file>assets/images/coldcard_unpaired.png</file>
<file>assets/images/confirmed.png</file>
<file>assets/images/confirmed_icon.png</file>
<file>assets/images/confirmed.svg</file>
<file>assets/images/connect.svg</file>
<file>assets/images/copy.png</file>
@@ -30,10 +31,13 @@
<file>assets/images/edit.png</file>
<file>assets/images/exchange.png</file>
<file>assets/images/expired.png</file>
<file>assets/images/expired_icon.png</file>
<file>assets/images/eye1.png</file>
<file>assets/images/eye_blind.png</file>
<file>assets/images/feather.png</file>
<file>assets/images/file.png</file>
<file>assets/images/ghost.png</file>
<file>assets/images/ghost_icon.png</file>
<file>assets/images/history.png</file>
<file>assets/images/info.png</file>
<file>assets/images/key.png</file>
@@ -41,8 +45,10 @@
<file>assets/images/ledger_unpaired.png</file>
<file>assets/images/lightning.png</file>
<file>assets/images/lock.png</file>
<file>assets/images/lock_icon.png</file>
<file>assets/images/lock.svg</file>
<file>assets/images/microphone.png</file>
<file>assets/images/morphtoken.png</file>
<file>assets/images/network.png</file>
<file>assets/images/offline_tx.png</file>
<file>assets/images/person.svg</file>
@@ -91,6 +97,8 @@
<file>assets/images/warning.png</file>
<file>assets/images/xmrto_big.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/mnemonic_25_english.txt</file>
<file>assets/restore_heights_monero_mainnet.txt</file>
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.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 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

-5
View File
@@ -1,5 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor</file>
</qresource>
</RCC>
@@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor.exe</file>
<file>assets/exec/xmrig</file>
</qresource>
</RCC>
@@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor</file>
<file>assets/exec/tor</file>
</qresource>
</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>
+2 -7
View File
@@ -13,6 +13,7 @@ CalcWidget::CalcWidget(QWidget *parent) :
ui(new Ui::CalcWidget)
{
ui->setupUi(this);
m_ctx = MainWindow::getContext();
ui->imageExchange->setBackgroundRole(QPalette::Base);
QPixmap pm(":/assets/images/exchange.png");
@@ -106,21 +107,15 @@ void CalcWidget::toComboChanged(const QString &data) {
}
void CalcWidget::initCrypto() {
if (this->m_ctx == nullptr)
this->m_ctx = MainWindow::getContext();
this->initComboBox();
}
void CalcWidget::initFiat() {
if(this->m_ctx == nullptr)
this->m_ctx = MainWindow::getContext();
this->initComboBox();
}
void CalcWidget::initComboBox() {
if(m_comboBoxInit || this->m_ctx == nullptr) return;
if(m_comboBoxInit) return;
QList<QString> marketsKeys = AppContext::prices->markets.keys();
QList<QString> ratesKeys = AppContext::prices->rates.keys();
if(marketsKeys.count() <= 0 || ratesKeys.count() <= 0) return;
+1 -1
View File
@@ -31,7 +31,7 @@ public slots:
private:
Ui::CalcWidget *ui;
AppContext *m_ctx = nullptr;
AppContext *m_ctx;
bool m_comboBoxInit = false;
void initComboBox();
bool m_changing = false;
+1 -1
View File
@@ -58,7 +58,7 @@ void CLI::onWalletOpenedError(const QString &err) {
return this->finishedError(err);
}
void CLI::onWalletOpenPasswordRequired(bool invalidPassword) {
void CLI::onWalletOpenPasswordRequired(bool invalidPassword, const QString &path) {
if(mode == CLIMode::CLIModeExportContacts ||
mode == CLIMode::CLIModeExportTxHistory)
return this->finishedError("invalid password");
+1 -1
View File
@@ -26,7 +26,7 @@ public slots:
//libwalletqt
void onWalletOpened();
void onWalletOpenedError(const QString& err);
void onWalletOpenPasswordRequired(bool invalidPassword);
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
private:
AppContext *ctx;
+24 -9
View File
@@ -7,6 +7,7 @@
#include "utils/utils.h"
#include "dialog/outputinfodialog.h"
#include "dialog/outputsweepdialog.h"
#include "mainwindow.h"
#include <QClipboard>
#include <QDebug>
@@ -21,6 +22,7 @@ CoinsWidget::CoinsWidget(QWidget *parent)
, m_copyMenu(new QMenu("Copy",this))
{
ui->setupUi(this);
m_ctx = MainWindow::getContext();
// header context menu
ui->coins->header()->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -40,14 +42,14 @@ CoinsWidget::CoinsWidget(QWidget *parent)
// context menu
ui->coins->setContextMenuPolicy(Qt::CustomContextMenu);
m_thawOutputAction = new QAction("Thaw output");
m_freezeOutputAction = new QAction("Freeze output");
m_thawOutputAction = new QAction("Thaw output", this);
m_freezeOutputAction = new QAction("Freeze output", this);
m_freezeAllSelectedAction = new QAction("Freeze selected");
m_thawAllSelectedAction = new QAction("Thaw selected");
m_freezeAllSelectedAction = new QAction("Freeze selected", this);
m_thawAllSelectedAction = new QAction("Thaw selected", this);
m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details");
m_sweepOutputAction = new QAction("Sweep output");
m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details", this);
m_sweepOutputAction = new QAction("Sweep output", this);
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput);
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
@@ -57,18 +59,25 @@ CoinsWidget::CoinsWidget(QWidget *parent)
connect(m_thawAllSelectedAction, &QAction::triggered, this, &CoinsWidget::thawAllSelected);
connect(ui->coins, &QTreeView::customContextMenuRequested, this, &CoinsWidget::showContextMenu);
connect(ui->coins, &QTreeView::doubleClicked, this, &CoinsWidget::viewOutput);
}
void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
m_coins = coins;
m_model = model;
m_proxyModel = new CoinsProxyModel;
m_proxyModel = new CoinsProxyModel(this);
m_proxyModel->setSourceModel(m_model);
ui->coins->setModel(m_proxyModel);
ui->coins->setColumnHidden(CoinsModel::Spent, true);
ui->coins->setColumnHidden(CoinsModel::SpentHeight, 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(CoinsModel::AddressLabel, QHeaderView::Stretch);
ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder);
@@ -102,10 +111,15 @@ void CoinsWidget::showContextMenu(const QPoint &point) {
if (!isSpent) {
isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction);
}
if (!isFrozen && isUnlocked) {
menu->addAction(m_sweepOutputAction);
if (isFrozen || !isUnlocked) {
m_sweepOutputAction->setDisabled(true);
} else {
m_sweepOutputAction->setEnabled(true);
}
}
menu->addAction(m_viewOutputAction);
}
@@ -193,6 +207,7 @@ void CoinsWidget::onSweepOutput() {
qCritical() << "key image: " << keyImage;
emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs());
dialog->deleteLater();
}
void CoinsWidget::copy(copyField field) {
+1
View File
@@ -67,6 +67,7 @@ private:
Coins *m_coins;
CoinsModel * m_model;
CoinsProxyModel * m_proxyModel;
AppContext *m_ctx;
void showContextMenu(const QPoint & point);
void copy(copyField field);
+1 -3
View File
@@ -68,9 +68,7 @@ HelpLabel::HelpLabel(QWidget *parent) : QLabel(parent)
void HelpLabel::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event)
QMessageBox msgBox(QApplication::activeWindow());
msgBox.setText(this->help_text);
msgBox.exec();
QMessageBox::information(this, "Help", this->help_text);
}
void HelpLabel::enterEvent(QEvent *event)
+1 -1
View File
@@ -53,7 +53,7 @@
<item>
<widget class="QPlainTextEdit" name="copyrightText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
+62
View File
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "broadcasttxdialog.h"
#include "ui_broadcasttxdialog.h"
#include <QMessageBox>
BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx)
: 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);
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
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);
~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
+111
View File
@@ -0,0 +1,111 @@
<?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>
<widget class="QLabel" name="label_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>All transactions are broadcast over Tor</string>
</property>
</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>
+47 -33
View File
@@ -12,15 +12,26 @@
DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent)
: QDialog(parent)
, ui(new Ui::DebugInfoDialog)
, m_ctx(ctx)
{
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;
if(ctx->isTorSocks)
if(m_ctx->isTorSocks)
torStatus = "Torsocks";
else if(ctx->tor->localTor)
else if(m_ctx->tor->localTor)
torStatus = "Local (assumed to be running)";
else if(ctx->tor->torConnected)
else if(m_ctx->tor->torConnected)
torStatus = "Running";
else
torStatus = "Unknown";
@@ -28,27 +39,28 @@ DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent)
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_walletHeight->setText(QString::number(ctx->currentWallet->blockChainHeight()));
ui->label_daemonHeight->setText(QString::number(ctx->currentWallet->daemonBlockChainHeight()));
ui->label_restoreHeight->setText(QString::number(ctx->currentWallet->getWalletCreationHeight()));
ui->label_synchronized->setText(ctx->currentWallet->synchronized() ? "True" : "False");
ui->label_walletHeight->setText(QString::number(m_ctx->currentWallet->blockChainHeight()));
ui->label_daemonHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainHeight()));
ui->label_targetHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainTargetHeight()));
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_walletStatus->setText(this->statusToString(ctx->currentWallet->connected()));
ui->label_walletStatus->setText(this->statusToString(m_ctx->currentWallet->connectionStatus()));
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_seedType->setText(ctx->currentWallet->getCacheAttribute("feather.seed").isEmpty() ? "25 word" : "14 word");
ui->label_viewOnly->setText(ctx->currentWallet->viewOnly() ? "True" : "False");
ui->label_netType->setText(Utils::QtEnumToString(m_ctx->currentWallet->nettype()));
ui->label_seedType->setText(m_ctx->currentWallet->getCacheAttribute("feather.seed").isEmpty() ? "25 word" : "14 word");
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()));
connect(ui->btn_Copy, &QPushButton::clicked, this, &DebugInfoDialog::copyToClipboad);
this->adjustSize();
}
QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
@@ -67,26 +79,28 @@ QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
}
void DebugInfoDialog::copyToClipboad() {
// Two spaces at the end of each line are for newlines in Markdown
QString 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("Feather version: %1 \n").arg(ui->label_featherVersion->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("Daemon height: %1\n").arg(ui->label_daemonHeight->text());
text += QString("Restore height: %1\n").arg(ui->label_restoreHeight->text());
text += QString("Synchronized: %1\n").arg(ui->label_synchronized->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("Target height: %1 \n").arg(ui->label_targetHeight->text());
text += QString("Restore height: %1 \n").arg(ui->label_restoreHeight->text());
text += QString("Synchronized: %1 \n").arg(ui->label_synchronized->text());
text += QString("Remote node: %1\n").arg(ui->label_remoteNode->text());
text += QString("Wallet status: %1\n").arg(ui->label_walletStatus->text());
text += QString("Tor status: %1\n").arg(ui->label_torStatus->text());
text += QString("Websocket status: %1\n").arg(ui->label_websocketStatus->text());
text += QString("Remote node: %1 \n").arg(ui->label_remoteNode->text());
text += QString("Wallet status: %1 \n").arg(ui->label_walletStatus->text());
text += QString("Tor status: %1 \n").arg(ui->label_torStatus->text());
text += QString("Websocket status: %1 \n").arg(ui->label_websocketStatus->text());
text += QString("Network type: %1\n").arg(ui->label_netType->text());
text += QString("Seed type: %1\n").arg(ui->label_seedType->text());
text += QString("View only: %1\n").arg(ui->label_viewOnly->text());
text += QString("Network type: %1 \n").arg(ui->label_netType->text());
text += QString("Seed type: %1 \n").arg(ui->label_seedType->text());
text += QString("View only: %1 \n").arg(ui->label_viewOnly->text());
text += QString("Operating system: %1\n").arg(ui->label_OS->text());
text += QString("Timestamp: %1\n").arg(ui->label_timestamp->text());
text += QString("Operating system: %1 \n").arg(ui->label_OS->text());
text += QString("Timestamp: %1 \n").arg(ui->label_timestamp->text());
Utils::copyToClipboard(text);
}
+4
View File
@@ -23,6 +23,10 @@ public:
private:
QString statusToString(Wallet::ConnectionStatus status);
void copyToClipboad();
void updateInfo();
QTimer m_updateTimer;
AppContext *m_ctx;
Ui::DebugInfoDialog *ui;
};
+46 -26
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>693</width>
<height>580</height>
<height>612</height>
</rect>
</property>
<property name="windowTitle">
@@ -91,14 +91,14 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Restore height:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QLabel" name="label_restoreHeight">
<property name="text">
<string>TextLabel</string>
@@ -108,14 +108,14 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Synchronized:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QLabel" name="label_synchronized">
<property name="text">
<string>TextLabel</string>
@@ -125,21 +125,21 @@
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Remote node:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QLabel" name="label_remoteNode">
<property name="text">
<string>TextLabel</string>
@@ -149,14 +149,14 @@
</property>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Wallet status:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QLabel" name="label_walletStatus">
<property name="text">
<string>TextLabel</string>
@@ -166,14 +166,14 @@
</property>
</widget>
</item>
<item row="10" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Tor status:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QLabel" name="label_torStatus">
<property name="text">
<string>TextLabel</string>
@@ -183,14 +183,14 @@
</property>
</widget>
</item>
<item row="11" column="0">
<item row="12" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Websocket status:</string>
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QLabel" name="label_websocketStatus">
<property name="text">
<string>TextLabel</string>
@@ -200,21 +200,21 @@
</property>
</widget>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="13" column="0">
<item row="14" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Network type:</string>
</property>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QLabel" name="label_netType">
<property name="text">
<string>TextLabel</string>
@@ -224,14 +224,14 @@
</property>
</widget>
</item>
<item row="14" column="0">
<item row="15" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Seed type:</string>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="15" column="1">
<widget class="QLabel" name="label_seedType">
<property name="text">
<string>TextLabel</string>
@@ -241,14 +241,14 @@
</property>
</widget>
</item>
<item row="15" column="0">
<item row="16" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>View only:</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="16" column="1">
<widget class="QLabel" name="label_viewOnly">
<property name="text">
<string>TextLabel</string>
@@ -258,14 +258,14 @@
</property>
</widget>
</item>
<item row="18" column="0">
<item row="19" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Timestamp:</string>
</property>
</widget>
</item>
<item row="18" column="1">
<item row="19" column="1">
<widget class="QLabel" name="label_timestamp">
<property name="text">
<string>TextLabel</string>
@@ -275,27 +275,47 @@
</property>
</widget>
</item>
<item row="17" column="0">
<item row="18" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Operating system:</string>
</property>
</widget>
</item>
<item row="17" column="1">
<item row="18" column="1">
<widget class="QLabel" name="label_OS">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="16" column="1">
<item row="17" column="1">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
</item>
<item>
+46 -11
View File
@@ -5,17 +5,39 @@
#include "ui_passwordchangedialog.h"
#include <QPushButton>
#include <QMessageBox>
PasswordChangeDialog::PasswordChangeDialog(QWidget *parent)
PasswordChangeDialog::PasswordChangeDialog(QWidget *parent, Wallet *wallet)
: QDialog(parent)
, ui(new Ui::PasswordChangeDialog)
, m_wallet(wallet)
{
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_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();
}
@@ -24,15 +46,28 @@ PasswordChangeDialog::~PasswordChangeDialog()
delete ui;
}
QString PasswordChangeDialog::getCurrentPassword() {
return ui->lineEdit_currentPassword->text();
}
QString PasswordChangeDialog::getNewPassword() {
return ui->lineEdit_newPassword->text();
}
void PasswordChangeDialog::passwordsMatch() {
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
#include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui {
class PasswordChangeDialog;
@@ -15,16 +16,15 @@ class PasswordChangeDialog : public QDialog
Q_OBJECT
public:
explicit PasswordChangeDialog(QWidget *parent = nullptr);
explicit PasswordChangeDialog(QWidget *parent, Wallet *wallet);
~PasswordChangeDialog() override;
QString getCurrentPassword();
QString getNewPassword();
private:
Ui::PasswordChangeDialog *ui;
Wallet *m_wallet;
void passwordsMatch();
void setPassword();
};
#endif //FEATHER_PASSWORDCHANGEDIALOG_H
+60 -46
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>237</height>
<width>556</width>
<height>309</height>
</rect>
</property>
<property name="sizePolicy">
@@ -30,7 +30,7 @@
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="label_warning">
<property name="text">
<string>Your wallet is password protected and encrypted. Use this dialog to change your password.</string>
</property>
@@ -41,6 +41,22 @@
</item>
</layout>
</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>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
@@ -65,7 +81,7 @@
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<widget class="QLabel" name="label_currentPassword">
<property name="text">
<string>Current Password:</string>
</property>
@@ -88,14 +104,45 @@
</layout>
</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>
<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">
<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_Cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_OK">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@@ -105,38 +152,5 @@
<tabstop>lineEdit_confirmPassword</tabstop>
</tabstops>
<resources/>
<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>
<connections/>
</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>
+8 -5
View File
@@ -9,15 +9,14 @@
#include <QFileDialog>
#include <QMessageBox>
QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &title)
QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title)
: QDialog(parent)
, ui(new Ui::QrCodeDialog)
{
ui->setupUi(this);
this->setWindowTitle(title);
m_qrc = new QrCode(text, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
m_pixmap = m_qrc->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
ui->QrCode->setPixmap(m_pixmap);
connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage);
@@ -32,7 +31,11 @@ QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &
QrCodeDialog::~QrCodeDialog()
{
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() {
@@ -41,7 +44,7 @@ void QrCodeDialog::copyImage() {
}
void QrCodeDialog::saveImage() {
QString filename = QFileDialog::getSaveFileName(this, "Select where to save file", "qrcode.png");
QString filename = QFileDialog::getSaveFileName(this, "Select where to save file", QDir::current().filePath("qrcode.png"));
if (filename.isEmpty()) {
return;
}
+2 -2
View File
@@ -16,15 +16,15 @@ class QrCodeDialog : public QDialog
Q_OBJECT
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;
void setQrCode(const QrCode &qrCode);
private:
void copyImage();
void saveImage();
Ui::QrCodeDialog *ui;
QrCode *m_qrc;
QPixmap m_pixmap;
};
+36 -12
View File
@@ -4,27 +4,51 @@
#include "ui_seeddialog.h"
#include "seeddialog.h"
SeedDialog::SeedDialog(const QString &seed, QWidget *parent)
SeedDialog::SeedDialog(Wallet *wallet, QWidget *parent)
: QDialog(parent)
, ui(new Ui::SeedDialog)
{
ui->setupUi(this);
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->widgetRestoreHeight->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->widgetRestoreHeight->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);
int words = seed.split(" ").size();
ui->label_warning->setText(QString("<p>Please save these %1 words on paper (order is important). "
"This seed will allow you to recover your wallet in case "
"of computer failure."
"</p>"
"<b>WARNING:</b>"
"<ul>"
"<li>Never disclose your seed.</li>"
"<li>Never type it on a website</li>"
"<li>Do not store it electronically</li>"
"</ul>").arg(words));
this->adjustSize();
"This seed will allow you to recover your wallet in case "
"of computer failure."
"</p>"
"<b>WARNING:</b>"
"<ul>"
"<li>Never disclose your seed.</li>"
"<li>Never type it on a website</li>"
"<li>Do not store it electronically</li>"
"</ul>").arg(words));
}
SeedDialog::~SeedDialog()
+4 -1
View File
@@ -5,6 +5,7 @@
#define FEATHER_SEEDDIALOG_H
#include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui {
class SeedDialog;
@@ -15,10 +16,12 @@ class SeedDialog : public QDialog
Q_OBJECT
public:
explicit SeedDialog(const QString& seed, QWidget *parent = nullptr);
explicit SeedDialog(Wallet *wallet, QWidget *parent = nullptr);
~SeedDialog() override;
private:
void setSeed(const QString &seed);
Ui::SeedDialog *ui;
};
+94 -22
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>542</width>
<height>244</height>
<width>590</width>
<height>346</height>
</rect>
</property>
<property name="windowTitle">
@@ -34,29 +34,94 @@
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="seed">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>125</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPlainTextEdit" name="seed">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>125</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>300</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRestoreHeight" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<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="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>
</item>
<item>
<widget class="QCheckBox" name="check_toggleSeedType">
<property name="text">
<string>Show 25 word seed</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_warning">
<property name="text">
@@ -79,6 +144,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HelpLabel</class>
<extends>QLabel</extends>
<header>components.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
+19 -6
View File
@@ -6,18 +6,29 @@
#include "libwalletqt/CoinsInfo.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)
, ui(new Ui::TransactionInfoDialog)
, m_coins(coins)
, m_wallet(wallet)
, m_txInfo(txInfo)
{
ui->setupUi(this);
ui->txid->setText(QString(txInfo->hash()));
ui->txid->setCursorPosition(0);
m_txProofWidget = new TxProofWidget(this, wallet, txInfo);
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);
}
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")));
@@ -30,7 +41,7 @@ TransactionInfoDialog::TransactionInfoDialog(Coins *coins, TransactionInfo *txIn
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()));
qDebug() << m_coins->coins_from_txid(txInfo->hash());
qDebug() << m_wallet->coins()->coins_from_txid(txInfo->hash());
QString destinations = txInfo->destinations_formatted();
if (destinations.isEmpty()) {
@@ -41,6 +52,8 @@ TransactionInfoDialog::TransactionInfoDialog(Coins *coins, TransactionInfo *txIn
ui->destinations->setText(destinations);
}
ui->txProofWidget->addWidget(m_txProofWidget);
this->adjustSize();
}
+5 -2
View File
@@ -8,6 +8,8 @@
#include <QtSvg/QSvgWidget>
#include "libwalletqt/Coins.h"
#include "libwalletqt/TransactionInfo.h"
#include "libwalletqt/Wallet.h"
#include "widgets/txproofwidget.h"
namespace Ui {
class TransactionInfoDialog;
@@ -18,14 +20,15 @@ class TransactionInfoDialog : public QDialog
Q_OBJECT
public:
explicit TransactionInfoDialog(Coins *coins, TransactionInfo *txInfo, QWidget *parent = nullptr);
explicit TransactionInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent = nullptr);
~TransactionInfoDialog() override;
private:
Ui::TransactionInfoDialog *ui;
TransactionInfo *m_txInfo;
Coins *m_coins;
Wallet *m_wallet;
TxProofWidget *m_txProofWidget;
};
#endif //FEATHER_TRANSACTIONINFODIALOG_H
+41 -22
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>332</height>
<width>829</width>
<height>570</height>
</rect>
</property>
<property name="windowTitle">
@@ -15,32 +15,41 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="text">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Transaction ID:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_txid">
<property name="text">
<string>txid</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLineEdit" name="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">
<string>txid</string>
</property>
<property name="readOnly">
<bool>true</bool>
<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>
@@ -149,6 +158,16 @@
</property>
</widget>
</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>
<spacer name="verticalSpacer">
<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>
+14 -23
View File
@@ -6,12 +6,16 @@
#include "appcontext.h"
#include "utils/config.h"
#include "model/ModelUtils.h"
#include "libwalletqt/WalletManager.h"
#include "txconfadvdialog.h"
#include "globals.h"
#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)
, ui(new Ui::TxConfDialog)
, m_ctx(ctx)
, m_tx(tx)
, m_address(address)
, m_description(description)
@@ -28,44 +32,31 @@ TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const
};
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));
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));
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_address->setText(ModelUtils::displayAddress(address, 2));
ui->label_address->setFont(ModelUtils::getMonospaceFont());
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);
this->adjustSize();
}
void TxConfDialog::showAdvanced() {
const auto amount = m_tx->amount() / AppContext::cdiv;
const auto fee = m_tx->fee() / AppContext::cdiv;
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);
void TxConfDialog::setShowAdvanced() {
this->showAdvanced = true;
QDialog::reject();
}
TxConfDialog::~TxConfDialog() {
+8 -2
View File
@@ -7,6 +7,7 @@
#include <QDialog>
#include "libwalletqt/PendingTransaction.h"
#include "libwalletqt/WalletManager.h"
#include "appcontext.h"
namespace Ui {
class TxConfDialog;
@@ -17,13 +18,18 @@ class TxConfDialog : public QDialog
Q_OBJECT
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;
bool showAdvanced = false;
private:
void showAdvanced();
void setShowAdvanced();
void saveToFile();
void copyToClipboard();
Ui::TxConfDialog *ui;
AppContext *m_ctx;
PendingTransaction *m_tx;
QString m_address;
QString m_description;
+14 -2
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>655</width>
<height>232</height>
<width>844</width>
<height>248</height>
</rect>
</property>
<property name="windowTitle">
@@ -46,6 +46,9 @@
<property name="text">
<string>address</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
@@ -60,6 +63,9 @@
<property name="text">
<string>amount</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
@@ -74,6 +80,9 @@
<property name="text">
<string>fee</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
@@ -95,6 +104,9 @@
<property name="text">
<string>total</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
+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>
+35 -19
View File
@@ -16,26 +16,28 @@ VerifyProofDialog::VerifyProofDialog(Wallet *wallet, QWidget *parent)
{
ui->setupUi(this);
connect(ui->btn_verifySpendProof, &QPushButton::clicked, this, &VerifyProofDialog::checkSpendProof);
connect(ui->btn_verifyOutProof, &QPushButton::clicked, this, &VerifyProofDialog::checkOutProof);
connect(ui->btn_verifyInProof, &QPushButton::clicked, this, &VerifyProofDialog::checkInProof);
connect(ui->btn_verify, &QPushButton::clicked, this, &VerifyProofDialog::checkProof);
connect(ui->btn_spendClear, &QPushButton::clicked, [this](){
ui->lineEdit_spendTxID->clear();
ui->lineEdit_spendMessage->clear();
ui->input_SpendProof->clear();
});
connect(ui->btn_outClear, &QPushButton::clicked, [this](){
ui->lineEdit_outTxID->clear();
ui->lineEdit_outAddress->clear();
ui->lineEdit_outMessage->clear();
ui->input_OutProof->clear();
});
connect(ui->btn_inClear, &QPushButton::clicked, [this](){
ui->lineEdit_inTxID->clear();
ui->lineEdit_inAddress->clear();
ui->lineEdit_inMessage->clear();
ui->input_InProof->clear();
connect(ui->btn_clear, &QPushButton::clicked, [this]{
switch (ui->tabWidget->currentIndex()) {
case 0:
ui->lineEdit_spendTxID->clear();
ui->lineEdit_spendMessage->clear();
ui->input_SpendProof->clear();
break;
case 1:
ui->lineEdit_outTxID->clear();
ui->lineEdit_outAddress->clear();
ui->lineEdit_outMessage->clear();
ui->input_OutProof->clear();
break;
case 2:
ui->lineEdit_inTxID->clear();
ui->lineEdit_inAddress->clear();
ui->lineEdit_inMessage->clear();
ui->input_InProof->clear();
break;
}
});
}
@@ -44,6 +46,20 @@ VerifyProofDialog::~VerifyProofDialog()
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() {
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;
private slots:
void checkSpendProof();
void checkOutProof();
void checkInProof();
void checkProof();
private:
void checkTxProof(const QString &txId, const QString &address, const QString &message, const QString &signature);
void checkSpendProof();
void checkOutProof();
void checkInProof();
Ui::VerifyProofDialog *ui;
Wallet *m_wallet;
+48 -107
View File
@@ -39,17 +39,7 @@
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<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>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
@@ -57,10 +47,13 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_spendTxID"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>SpendProof:</string>
<string>Transaction ID:</string>
</property>
</widget>
</item>
@@ -71,6 +64,13 @@
</property>
</widget>
</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">
<widget class="QPlainTextEdit" name="input_SpendProof">
<property name="overwriteMode">
@@ -96,37 +96,6 @@
</property>
</spacer>
</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>
</widget>
<widget class="QWidget" name="OutProof">
@@ -213,37 +182,6 @@
</property>
</spacer>
</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>
</widget>
<widget class="QWidget" name="InProof">
@@ -331,41 +269,44 @@
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<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_inClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verifyInProof">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</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_clear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verify">
<property name="text">
<string>Verify</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
+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() {
QFileInfo file(m_ctx->walletPath);
QDesktopServices::openUrl(file.absolutePath());
QDesktopServices::openUrl(QUrl(QString("file://%1").arg(file.absolutePath()), QUrl::TolerantMode));
}
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
+18 -5
View File
@@ -25,23 +25,36 @@ HistoryWidget::HistoryWidget(QWidget *parent)
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);});
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof);
auto spendProof = m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof);
ui->history->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){
QModelIndex index = ui->history->indexAt(point);
if (index.isValid()) {
TransactionInfo::Direction direction;
m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction](TransactionInfo &tInfo) {
direction = tInfo.direction();
});
spendProof->setVisible(direction == TransactionInfo::Direction_Out);
m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point));
}
});
connect(ui->search, &QLineEdit::textChanged, this, &HistoryWidget::setSearchFilter);
connect(ui->history, &QTreeView::doubleClicked, [this](QModelIndex index){
if (m_model == nullptr) return;
if (!(m_model->flags(index) & Qt::ItemIsEditable)) {
this->showTxDetails();
}
});
}
void HistoryWidget::setModel(Coins *coins, TransactionHistoryProxyModel *model, TransactionHistory *txHistory)
void HistoryWidget::setModel(TransactionHistoryProxyModel *model, Wallet *wallet)
{
m_coins = coins;
m_model = model;
m_txHistory = txHistory;
m_wallet = wallet;
m_txHistory = m_wallet->history();
ui->history->setModel(m_model);
ui->history->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
@@ -58,7 +71,7 @@ void HistoryWidget::showTxDetails() {
});
if (i != nullptr) {
auto * dialog = new TransactionInfoDialog(m_coins, i, this);
auto * dialog = new TransactionInfoDialog(m_wallet, i, this);
dialog->exec();
}
}
+3 -2
View File
@@ -7,6 +7,7 @@
#include "model/TransactionHistoryModel.h"
#include "model/TransactionHistoryProxyModel.h"
#include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h"
#include <QWidget>
#include <QMenu>
@@ -21,7 +22,7 @@ Q_OBJECT
public:
explicit HistoryWidget(QWidget *parent = nullptr);
void setModel(Coins * coins, TransactionHistoryProxyModel * model, TransactionHistory * txHistory);
void setModel(TransactionHistoryProxyModel *model, Wallet *wallet);
~HistoryWidget() override;
public slots:
@@ -51,7 +52,7 @@ private:
QMenu *m_copyMenu;
TransactionHistory *m_txHistory;
TransactionHistoryProxyModel *m_model;
Coins *m_coins;
Wallet *m_wallet = nullptr;
};
#endif //FEATHER_HISTORYWIDGET_H
+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()
{
// Save transaction to file if fileName is set.
if(!m_fileName.isEmpty())
return m_pimpl->commit(m_fileName.toStdString());
return m_pimpl->commit(m_fileName.toStdString());
return m_pimpl->commit();
}
bool PendingTransaction::saveToFile(const QString &fileName)
{
return m_pimpl->commit(fileName.toStdString());
}
quint64 PendingTransaction::amount() const
@@ -37,7 +39,6 @@ quint64 PendingTransaction::fee() const
return m_pimpl->fee();
}
QStringList PendingTransaction::txid() const
{
QStringList list;
@@ -63,9 +64,33 @@ QList<QVariant> PendingTransaction::subaddrIndices() const
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)
+12 -4
View File
@@ -9,6 +9,8 @@
#include <QVariant>
#include <wallet/api/wallet2_api.h>
#include "PendingTransactionInfo.h"
//namespace Monero {
//class PendingTransaction;
@@ -30,7 +32,7 @@ public:
enum Status {
Status_Ok = Monero::PendingTransaction::Status_Ok,
Status_Error = Monero::PendingTransaction::Status_Error,
Status_Critical = Monero::PendingTransaction::Status_Critical
Status_Critical = Monero::PendingTransaction::Status_Critical
};
Q_ENUM(Status)
@@ -45,21 +47,27 @@ public:
Status status() const;
QString errorString() const;
Q_INVOKABLE bool commit();
bool saveToFile(const QString &fileName);
quint64 amount() const;
quint64 dust() const;
quint64 fee() const;
QStringList txid() const;
quint64 txCount() 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:
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = 0);
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = nullptr);
private:
friend class Wallet;
Monero::PendingTransaction * m_pimpl;
QString m_fileName;
mutable QList<PendingTransactionInfo*> m_pending_tx_info;
};
#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;
}
quint64 TransactionInfo::balanceDelta() const
{
return m_amount + m_fee;
}
double TransactionInfo::amount() const
{
// there's no unsigned uint64 for JS, so better use double
@@ -44,6 +49,11 @@ QString TransactionInfo::displayAmount() const
return WalletManager::displayAmount(m_amount);
}
quint64 TransactionInfo::atomicFee() const
{
return m_fee;
}
QString TransactionInfo::fee() const
{
if(m_fee == 0)
@@ -127,6 +137,15 @@ QString TransactionInfo::destinations_formatted() const
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 rings;
+3
View File
@@ -52,10 +52,12 @@ public:
bool isPending() const;
bool isFailed() const;
bool isCoinbase() const;
quint64 balanceDelta() const;
double amount() const;
quint64 atomicAmount() const;
QString displayAmount() const;
QString fee() const;
quint64 atomicFee() const;
quint64 blockHeight() const;
QString description() const;
QSet<quint32> subaddrIndex() const;
@@ -72,6 +74,7 @@ public:
QString paymentId() const;
//! only applicable for output transactions
//! used in tx details popup
QList<QString> destinations() const;
QString destinations_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)) {};
private:
friend class TransactionInfo;
friend class ConstructionInfo;
quint64 m_amount;
QString m_address;
public:
+15
View File
@@ -83,6 +83,21 @@ void UnsignedTransaction::setFilename(const QString &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)
: QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl)
{
+6 -3
View File
@@ -7,14 +7,13 @@
#include <QObject>
#include <wallet/api/wallet2_api.h>
#include "libwalletqt/PendingTransactionInfo.h"
class UnsignedTransaction : public QObject
{
Q_OBJECT
Q_PROPERTY(Status status READ status)
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(QString confirmationMessage READ confirmationMessage)
Q_PROPERTY(QStringList recipientAddress READ recipientAddress)
@@ -41,15 +40,19 @@ public:
quint64 minMixinCount() const;
Q_INVOKABLE bool sign(const QString &fileName) const;
Q_INVOKABLE void setFilename(const QString &fileName);
void refresh();
ConstructionInfo * constructionInfo(int index) const;
private:
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = 0);
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = nullptr);
~UnsignedTransaction();
private:
friend class Wallet;
Monero::UnsignedTransaction * m_pimpl;
QString m_fileName;
Monero::Wallet * m_walletImpl;
mutable QList<ConstructionInfo*> m_construction_info;
};
#endif // UNSIGNEDTRANSACTION_H
+276 -135
View File
@@ -2,6 +2,11 @@
// Copyright (c) 2014-2020, The Monero Project.
#include "Wallet.h"
#include <chrono>
#include <stdexcept>
#include <thread>
#include "PendingTransaction.h"
#include "UnsignedTransaction.h"
#include "TransactionHistory.h"
@@ -27,6 +32,8 @@
#include <QVector>
#include <QMutexLocker>
#include "utils/ScopeGuard.h"
namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@@ -36,10 +43,15 @@ namespace {
}
Wallet::Wallet(QObject * parent)
: Wallet(nullptr, parent)
: Wallet(nullptr, parent)
{
}
Wallet::ConnectionStatus Wallet::connectionStatus() const
{
return m_connectionStatus;
}
QString Wallet::getSeed() const
{
return QString::fromStdString(m_walletImpl->seed());
@@ -65,41 +77,28 @@ NetworkType::Type Wallet::nettype() const
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
{
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)
{
if (m_connectionStatus == value)
@@ -111,7 +110,7 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
emit connectionStatusChanged(m_connectionStatus);
bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting ||
m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
if (m_disconnected != disconnected)
{
@@ -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
{
return m_walletImpl->synchronized();
@@ -135,6 +157,11 @@ bool Wallet::setPassword(const QString &password)
return m_walletImpl->setPassword(password.toStdString());
}
QString Wallet::getPassword()
{
return QString::fromStdString(m_walletImpl->getPassword());
}
QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const
{
return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex));
@@ -145,20 +172,18 @@ QString Wallet::path() const
return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->path()));
}
//void Wallet::storeAsync(const QVariant &callback, const QString &path /* = "" */)
//void Wallet::storeAsync(const QJSValue &callback, const QString &path /* = "" */)
//{
// const auto future = m_scheduler.run(
// [this, path] {
// QMutexLocker locker(&m_storeMutex);
// return QVariantList({m_walletImpl->store(path.toStdString())});
// },
// callback);
// [this, path] {
// QMutexLocker locker(&m_asyncMutex);
//
// return QJSValueList({m_walletImpl->store(path.toStdString())});
// },
// callback);
// 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());
}
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";
if (isRecovering){
@@ -181,7 +206,20 @@ bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 uppe
if (isRecovering || isRecoveringFromDevice) {
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);
return true;
}
@@ -193,17 +231,24 @@ void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemon
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;
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight] {
bool success = init(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, proxyAddress);
if (success)
{
emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh";
connected(true);
m_walletImpl->startRefresh();
refreshHeightAsync();
startRefresh();
}
});
if (future.first)
@@ -246,6 +291,11 @@ void Wallet::setTrustedDaemon(bool arg)
m_walletImpl->setTrustedDaemon(arg);
}
void Wallet::setUseSSL(bool ssl)
{
m_useSSL = ssl;
}
bool Wallet::viewOnly() const
{
return m_walletImpl->watchOnly();
@@ -358,6 +408,8 @@ void Wallet::refreshHeightAsync()
daemonHeightFuture.second.waitForFinished();
targetHeightFuture.second.waitForFinished();
setConnectionStatus(ConnectionStatus_Connected);
emit heightRefreshed(walletHeight, daemonHeight, targetHeight);
});
}
@@ -372,7 +424,8 @@ quint64 Wallet::daemonBlockChainHeight() const
// cache daemon blockchain height for some time (60 seconds by default)
if (m_daemonBlockChainHeight == 0
|| m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl) {
|| m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl)
{
m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight();
m_daemonBlockChainHeightTime.restart();
}
@@ -382,7 +435,8 @@ quint64 Wallet::daemonBlockChainHeight() const
quint64 Wallet::daemonBlockChainTargetHeight() const
{
if (m_daemonBlockChainTargetHeight <= 1
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl)
{
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
// Target height is set to 0 if daemon is synced.
@@ -396,9 +450,9 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
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)
@@ -406,42 +460,40 @@ bool Wallet::importKeyImages(const QString& path)
return m_walletImpl->importKeyImages(path.toStdString());
}
bool Wallet::refresh()
{
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;
bool Wallet::exportOutputs(const QString& path, bool all) {
return m_walletImpl->exportOutputs(path.toStdString(), all);
}
void Wallet::refreshAsync()
{
qDebug() << "refresh async";
m_walletImpl->refreshAsync();
bool Wallet::importOutputs(const QString& path) {
return m_walletImpl->importOutputs(path.toStdString());
}
void Wallet::setAutoRefreshInterval(int seconds)
{
m_walletImpl->setAutoRefreshInterval(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;
for (const auto &o : output_indeces) {
o_indeces.push_back(o);
}
return m_walletImpl->importTransaction(
txid.toStdString(),
o_indeces,
height,
17, // todo: get actual block_version
timestamp,
miner_tx,
pool,
double_spend_seen);
}
int Wallet::autoRefreshInterval() const
void Wallet::startRefresh()
{
return m_walletImpl->autoRefreshInterval();
m_refreshEnabled = true;
m_refreshNow = true;
}
void Wallet::startRefresh() const
void Wallet::pauseRefresh()
{
m_walletImpl->startRefresh();
}
void Wallet::pauseRefresh() const
{
m_walletImpl->pauseRefresh();
m_refreshEnabled = false;
}
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -450,15 +502,15 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
{
std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl,0);
return result;
}
void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority)
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority)
{
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
@@ -471,15 +523,15 @@ PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const
{
std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl, this);
return result;
}
void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
quint32 mixin_count,
PendingTransaction::Priority priority)
quint32 mixin_count,
PendingTransaction::Priority priority)
{
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
@@ -501,7 +553,7 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
{
m_scheduler.run([this, 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;
}
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
{
qDebug() << "Trying to submit " << fileName;
@@ -537,6 +604,28 @@ bool Wallet::submitTxFile(const QString &fileName) const
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)
{
m_scheduler.run([this, t] {
@@ -556,7 +645,6 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
delete t;
}
// @ TODO: QJSValue could probably be QVARIANT
//void Wallet::estimateTransactionFeeAsync(const QString &destination,
// quint64 amount,
// PendingTransaction::Priority priority,
@@ -564,8 +652,8 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
//{
// m_scheduler.run([this, destination, amount, priority] {
// const uint64_t fee = m_walletImpl->estimateTransactionFee(
// {std::make_pair(destination.toStdString(), amount)},
// static_cast<Monero::PendingTransaction::Priority>(priority));
// {std::make_pair(destination.toStdString(), amount)},
// static_cast<Monero::PendingTransaction::Priority>(priority));
// return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
// }, callback);
//}
@@ -683,17 +771,17 @@ bool Wallet::setCacheAttribute(const QString &key, const QString &val)
bool Wallet::setUserNote(const QString &txid, const QString &note)
{
return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
}
QString Wallet::getUserNote(const QString &txid) const
{
return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
}
QString Wallet::getTxKey(const QString &txid) const
{
return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString()));
return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString()));
}
//void Wallet::getTxKeyAsync(const QString &txid, const QJSValue &callback)
@@ -713,12 +801,10 @@ QString Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QSt
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());
if (result.empty())
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString()));
}
//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};
}
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());
if (result.empty())
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString()));
}
//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());
}
}
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;
@@ -852,6 +935,8 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
bool Wallet::rescanSpent()
{
QMutexLocker locker(&m_asyncMutex);
return m_walletImpl->rescanSpent();
}
@@ -928,8 +1013,8 @@ QString Wallet::getRing(const QString &key_image)
{
if (!ring.isEmpty())
ring = ring + " ";
QString s;
s.setNum(out);
QString s;
s.setNum(out);
ring = ring + s;
}
return ring;
@@ -949,8 +1034,8 @@ QString Wallet::getRings(const QString &txid)
for (uint64_t out: cring.second)
{
ring = ring + " ";
QString s;
s.setNum(out);
QString s;
s.setNum(out);
ring = ring + s;
}
}
@@ -964,9 +1049,9 @@ bool Wallet::setRing(const QString &key_image, const QString &ring, bool relativ
foreach(QString str, strOuts)
{
uint64_t out;
bool ok;
out = str.toULong(&ok);
if (ok)
bool ok;
out = str.toULong(&ok);
if (ok)
cring.push_back(out);
}
return m_walletImpl->setRing(key_image.toStdString(), cring, relative);
@@ -992,6 +1077,14 @@ void Wallet::onWalletPassphraseNeeded(bool 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)
{
if (m_walletListener != nullptr)
@@ -1001,26 +1094,30 @@ void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device
}
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
: QObject(parent)
, m_walletImpl(w)
, m_history(nullptr)
, m_historyModel(nullptr)
, m_addressBook(nullptr)
, m_addressBookModel(nullptr)
, m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0)
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_disconnected(true)
, m_currentSubaddressAccount(0)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr)
, m_coinsModel(nullptr)
, m_scheduler(this)
: QObject(parent)
, m_walletImpl(w)
, m_history(nullptr)
, m_historyModel(nullptr)
, m_addressBook(nullptr)
, m_addressBookModel(nullptr)
, m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0)
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_disconnected(true)
, m_currentSubaddressAccount(0)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr)
, m_coinsModel(nullptr)
, m_refreshNow(false)
, m_refreshEnabled(false)
, m_refreshing(false)
, m_scheduler(this)
, m_useSSL(true)
{
m_history = new TransactionHistory(m_walletImpl->history(), this);
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
@@ -1038,11 +1135,16 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false;
m_daemonUsername = "";
m_daemonPassword = "";
startRefreshThread();
}
Wallet::~Wallet()
{
qDebug() << "~Wallet: Closing wallet";
qDebug("~Wallet: Closing wallet");
pauseRefresh();
m_walletImpl->stop();
m_scheduler.shutdownWaitForFinished();
@@ -1062,13 +1164,52 @@ Wallet::~Wallet()
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical)
qDebug("Not storing wallet cache");
else if( m_walletImpl->store(""))
qDebug("Wallet cache stored successfully");
else
qDebug("Error storing wallet cache");
// Don't store on wallet close for now
// else if( m_walletImpl->store(""))
// qDebug("Wallet cache stored successfully");
// else
// qDebug("Error storing wallet cache");
delete m_walletImpl;
m_walletImpl = NULL;
delete m_walletListener;
m_walletListener = NULL;
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);
}
}
+83 -30
View File
@@ -8,7 +8,6 @@
#include <QObject>
#include <QMutex>
#include <QList>
//#include <QJSValue>
#include <QtConcurrent/QtConcurrent>
#include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
@@ -20,14 +19,20 @@
#include "WalletListenerImpl.h"
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 TransactionHistoryModel;
class TransactionHistoryProxyModel;
class TransactionHistorySortFilterModel;
class AddressBook;
class AddressBookModel;
class Subaddress;
@@ -50,13 +55,14 @@ struct TxProofResult {
class Wallet : public QObject, public PassprasePrompter
{
Q_OBJECT
Q_OBJECT
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 seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status)
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(bool synchronized READ synchronized)
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 publicSpendKey READ getPublicSpendKey)
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)
public:
@@ -98,6 +105,9 @@ public:
Q_ENUM(ConnectionStatus)
//! return connection status
ConnectionStatus connectionStatus() const;
//! returns mnemonic seed
QString getSeed() const;
@@ -113,19 +123,19 @@ public:
//! returns network type of the wallet.
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
bool synchronized() const;
//! returns last operation's error message
QString errorString() const;
//! changes the password using existing parameters (path, seed, seed lang)
Q_INVOKABLE bool setPassword(const QString &password);
//! get current wallet password
Q_INVOKABLE QString getPassword();
//! returns wallet's public address
Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
@@ -138,7 +148,14 @@ public:
// Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = "");
//! 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
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
@@ -149,9 +166,15 @@ public:
//! connects to daemon
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);
//! indicates if ssl should be used to connect to daemon
Q_INVOKABLE void setUseSSL(bool ssl);
//! returns balance
Q_INVOKABLE quint64 balance() const;
Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
@@ -184,24 +207,22 @@ public:
Q_INVOKABLE void refreshHeightAsync();
//! 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);
//! 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
Q_INVOKABLE bool refresh();
//! 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;
Q_INVOKABLE bool refresh(bool historyAndSubaddresses = false);
// pause/resume refresh
Q_INVOKABLE void startRefresh() const;
Q_INVOKABLE void pauseRefresh() const;
Q_INVOKABLE void startRefresh();
Q_INVOKABLE void pauseRefresh();
//! returns current wallet's block height
//! (can be less than daemon's blockchain height when wallet sync in progress)
@@ -225,7 +246,7 @@ public:
//! creates transaction with all outputs
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
quint32 mixin_count, PendingTransaction::Priority priority);
quint32 mixin_count, PendingTransaction::Priority priority);
//! creates async transaction with all outputs
Q_INVOKABLE void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
@@ -248,6 +269,12 @@ public:
//! Sign a transfer from file
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
Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
@@ -327,11 +354,11 @@ public:
Q_INVOKABLE QString getTxKey(const QString &txid) const;
//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 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 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 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 QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
// Rescan spent outputs
@@ -372,6 +399,9 @@ public:
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
virtual void onWalletPassphraseNeeded(bool on_device) override;
Q_INVOKABLE quint64 getBytesReceived() const;
Q_INVOKABLE quint64 getBytesSent() const;
// TODO: setListenter() when it implemented in API
signals:
// emitted on every event happened with wallet
@@ -380,7 +410,7 @@ signals:
// emitted when refresh process finished (could take a long time)
// signalling only after we
void refreshed();
void refreshed(bool success);
void moneySpent(const QString &txId, quint64 amount);
void moneyReceived(const QString &txId, quint64 amount);
@@ -402,6 +432,8 @@ signals:
void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const;
void disconnectedChanged() const;
void proxyAddressChanged() const;
void refreshingChanged() const;
private:
Wallet(QObject * parent = nullptr);
@@ -409,10 +441,24 @@ private:
~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 refreshing() const;
void refreshingSet(bool value);
void onRefreshed(bool success);
void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const;
void setProxyAddress(QString address);
void startRefreshThread();
private:
friend class WalletManager;
@@ -445,13 +491,20 @@ private:
mutable SubaddressAccountModel * m_subaddressAccountModel;
Coins * m_coins;
mutable CoinsModel * m_coinsModel;
QMutex m_asyncMutex;
QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning;
QString m_daemonUsername;
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;
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
void WalletListenerImpl::refreshed()
void WalletListenerImpl::refreshed(bool success)
{
qDebug() << __FUNCTION__;
emit m_wallet->refreshed();
m_wallet->onRefreshed(success);
emit m_wallet->refreshed(success);
}
void WalletListenerImpl::onDeviceButtonRequest(uint64_t code)
+1 -1
View File
@@ -25,7 +25,7 @@ public:
virtual void updated() override;
// called when wallet refreshed by background thread or explicitly
virtual void refreshed() override;
virtual void refreshed(bool success) override;
virtual void onDeviceButtonRequest(uint64_t code) override;

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