Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eab5145f34 | ||
|
|
a2c7245e46 | ||
|
|
4aa57f2684 | ||
|
|
d8625fdb29 | ||
|
|
207180396f | ||
|
|
b544e6dfce | ||
|
|
bc2cac672a | ||
|
|
6003ffebec | ||
|
|
51b3781c09 | ||
|
|
14e3422423 | ||
|
|
0e5ab21205 | ||
|
|
a11dc3f4b2 | ||
|
|
f5255440e4 | ||
|
|
0dc196e76d | ||
|
|
136f877778 | ||
|
|
3b7731d44f | ||
|
|
b51e1f3b0c | ||
|
|
ae3c214c3f | ||
|
|
200f16ecf2 | ||
|
|
ecd840c03a | ||
|
|
7092116efd | ||
|
|
68c493b736 | ||
|
|
4f62d52e5e | ||
|
|
c8be1e4966 | ||
|
|
c964cd5349 | ||
|
|
3fbf58f64d | ||
|
|
bd4400a7f2 | ||
|
|
c0e4d48fae | ||
|
|
8668f2beb2 | ||
|
|
628da207d0 | ||
|
|
677f7df376 | ||
|
|
580675e8a0 | ||
|
|
900a9b3fac | ||
|
|
f8f1e824a1 | ||
|
|
441c32bc30 | ||
|
|
41a0fb3b10 | ||
|
|
a38912a348 | ||
|
|
d568e4e1b6 | ||
|
|
12849c8571 | ||
|
|
f7fb051b67 | ||
|
|
693a6bc0df | ||
|
|
ccd19edf2f | ||
|
|
f2f6bf30b3 | ||
|
|
45b3f1ebde | ||
|
|
b4af2f75b1 | ||
|
|
fdabaf3374 | ||
|
|
2e481507e8 | ||
|
|
9b4e0e29e4 | ||
|
|
80bd8e085d | ||
|
|
7d2748c0bc | ||
|
|
2c0b04559e | ||
|
|
4476741ace | ||
|
|
68f8be01ac | ||
|
|
d84ee4692d | ||
|
|
a0fe51f318 | ||
|
|
70810ce6a2 | ||
|
|
f75d1f546b | ||
|
|
6c8255b12b | ||
|
|
f39cdb393f | ||
|
|
d4fda0f5f3 | ||
|
|
9afefa75a0 | ||
|
|
32c21ae81b | ||
|
|
ca1c2fa5ba | ||
|
|
6619927a7d | ||
|
|
e805dd04cb | ||
|
|
dbc3bed669 | ||
|
|
55aab1683f | ||
|
|
33978bda4f | ||
|
|
4c9ece5025 | ||
|
|
a984d64add | ||
|
|
cb95e89773 | ||
|
|
f8361fb31c | ||
|
|
5ceac87e6e | ||
|
|
e058f3bad1 | ||
|
|
460a44ba34 | ||
|
|
8c197f26ea | ||
|
|
6f17a1dfaa | ||
|
|
2217ae602a | ||
|
|
75743e8897 | ||
|
|
169d14ab3a | ||
|
|
710556a580 | ||
|
|
15211ce5fa | ||
|
|
66f53d865e | ||
|
|
ea81b308f7 | ||
|
|
9016fa13dc | ||
|
|
cee70a997d | ||
|
|
041c11f618 | ||
|
|
c5f0962e40 | ||
|
|
85a06007a1 | ||
|
|
b6459d1b64 | ||
|
|
653e59f5ec | ||
|
|
71e28831d8 | ||
|
|
874748ea7f | ||
|
|
d3e55c4510 | ||
|
|
147ee8ef8b | ||
|
|
5ec641bc6f | ||
|
|
4a37be1ce7 | ||
|
|
d1b4db2be4 | ||
|
|
1e2fa51b98 | ||
|
|
743c5fa9a4 | ||
|
|
ae1d6a2d1c | ||
|
|
5e246519c2 | ||
|
|
8b5cb8ba2c | ||
|
|
3ea7e5932e | ||
|
|
97b4fcb958 | ||
|
|
80c1c66bea | ||
|
|
be61c803bf | ||
|
|
a0a307f3bd | ||
|
|
1d8f4f0bfd | ||
|
|
7c288570b1 | ||
|
|
02d71ebf02 | ||
|
|
6ef4eaa39f | ||
|
|
d3ee2744d4 | ||
|
|
61b54efb97 | ||
|
|
91b00da4af | ||
|
|
2b72624ec0 | ||
|
|
55bb304dc2 | ||
|
|
8ffd2293f4 | ||
|
|
3df2e591fe | ||
|
|
785771cb90 | ||
|
|
aa14a2dcbb | ||
|
|
c9e2ce3770 | ||
|
|
835e4aaca3 | ||
|
|
97900bcbe6 | ||
|
|
a9ec69afd0 | ||
|
|
a008f1f45f | ||
|
|
fbd6b8eb53 | ||
|
|
855755fea3 | ||
|
|
302e585af4 | ||
|
|
9592335fa1 | ||
|
|
c874220b4e | ||
|
|
5d792ddf4c | ||
|
|
e942685c23 | ||
|
|
11800bec35 | ||
|
|
1b1bb7d76d | ||
|
|
394ff96aa2 | ||
|
|
34c1ef6126 | ||
|
|
58af196f84 | ||
|
|
564ec31c2d | ||
|
|
0f96dd7fb5 | ||
|
|
f42fb96b9d | ||
|
|
8401b79bf9 | ||
|
|
c4c8a43eb7 | ||
|
|
ecc88e1d48 | ||
|
|
b73233df77 | ||
|
|
f94d4e6bb2 | ||
|
|
6cfd0794eb | ||
|
|
42a64f9b0a | ||
|
|
33a85e1bd8 | ||
|
|
fde578aac9 | ||
|
|
925ef56830 | ||
|
|
585c850dd5 | ||
|
|
72f33da508 | ||
|
|
480ecfd047 | ||
|
|
1a6024c697 | ||
|
|
a11dd576e4 | ||
|
|
9fed3eb171 | ||
|
|
20156a7440 | ||
|
|
ca5b1df7df | ||
|
|
474ee2100c | ||
|
|
1ccedea1dd | ||
|
|
70dd25c477 | ||
|
|
bce983a6a5 | ||
|
|
eb8d150a9d | ||
|
|
841739cee9 | ||
|
|
d4dbc748c8 | ||
|
|
5ce6c8933d | ||
|
|
f61355c409 | ||
|
|
edad1928ab | ||
|
|
4201167477 | ||
|
|
16414ba2e9 | ||
|
|
1d001322cc | ||
|
|
9d781d1b57 | ||
|
|
3453e5ef34 | ||
|
|
76da957b81 | ||
|
|
35438792a0 | ||
|
|
01966df866 | ||
|
|
e2eb32ce78 | ||
|
|
03f484c2ae | ||
|
|
c44ee73ed0 | ||
|
|
e6e669845c | ||
|
|
5a08bc353e | ||
|
|
c8bc66a287 | ||
|
|
3beb470bbd | ||
|
|
b875ee362e | ||
|
|
4e3a977995 | ||
|
|
eb801ed9d4 | ||
|
|
d9dfef021f | ||
|
|
d2d3978de6 | ||
|
|
02f7249e6e | ||
|
|
a3309cea91 | ||
|
|
137ef6da72 | ||
|
|
4f56147319 | ||
|
|
d58259cefe | ||
|
|
9be79bba48 | ||
|
|
64db32dca9 | ||
|
|
774b4ed15f | ||
|
|
d337653e53 | ||
|
|
b06b7fca2a | ||
|
|
169720002c | ||
|
|
d7135393cd | ||
|
|
1e4a442b16 | ||
|
|
519df3f5a1 | ||
|
|
2a03ca9eda | ||
|
|
ff5dff26bb | ||
|
|
cbd29e6290 | ||
|
|
0f3c005b60 | ||
|
|
39c1d3bbf7 | ||
|
|
b66aceccc8 | ||
|
|
e9a4a828d6 | ||
|
|
bd60e30c3f | ||
|
|
046b2cfc4c | ||
|
|
24133ac390 | ||
|
|
8aecf79647 | ||
|
|
780a35fabe | ||
|
|
0e7c773bfd | ||
|
|
11f8406be3 | ||
|
|
2c99454565 | ||
|
|
cd96abe545 | ||
|
|
d76b688ec4 | ||
|
|
ed47e8e05c | ||
|
|
268b87a803 | ||
|
|
318690681b | ||
|
|
b1e37e714d | ||
|
|
18b514351d | ||
|
|
63c120bdb0 | ||
|
|
96409ecc17 | ||
|
|
c1cba44cba | ||
|
|
7a1ac42b1e | ||
|
|
87fd142ffd | ||
|
|
62ad0d9527 | ||
|
|
4f9e4ac93d | ||
|
|
cb6f2873a9 | ||
|
|
20b741d30d | ||
|
|
7ed2ff15d5 | ||
|
|
da4b2d16ef | ||
|
|
4521223413 | ||
|
|
0dd81c4873 | ||
|
|
df2ff26c0f | ||
|
|
e657e2a6b0 | ||
|
|
34a63897d6 | ||
|
|
6279591d1b | ||
|
|
403b8140b3 | ||
|
|
71ba9f6d4a | ||
|
|
3d5dae1f42 | ||
|
|
78eabc5ae7 | ||
|
|
485fb89941 | ||
|
|
df280cdd91 | ||
|
|
9b96ece2f9 | ||
|
|
a44087b750 | ||
|
|
70cbf59ce8 | ||
|
|
4aeaf2660f | ||
|
|
9b7849c5be | ||
|
|
51a0f86652 | ||
|
|
fa6ee35fb0 | ||
|
|
b1160280fe | ||
|
|
7441d6cb4a | ||
|
|
23000c6e60 | ||
|
|
75edc6e5bb | ||
|
|
06f649cbb7 | ||
|
|
ff78b5a6c2 | ||
|
|
47d965c6cd | ||
|
|
d6c26d4159 | ||
|
|
78516f4546 | ||
|
|
49f072eea4 | ||
|
|
302c258e6b | ||
|
|
70f1846de6 | ||
|
|
ae2815c1c6 | ||
|
|
24993bc0b2 | ||
|
|
216b2e0c5e | ||
|
|
44a2fc30dc | ||
|
|
aee60f33b7 | ||
|
|
5d8700370b | ||
|
|
1ef29207d5 | ||
|
|
497567e61f | ||
|
|
15c51e2e2b | ||
|
|
c5a055eb70 | ||
|
|
1b9cc7c679 | ||
|
|
0f0b033fe4 | ||
|
|
3feda6d6c7 | ||
|
|
103965ef40 | ||
|
|
3ee5e003a7 | ||
|
|
96ac717ede | ||
|
|
d0260ce018 | ||
|
|
61a135e1c2 | ||
|
|
98db512164 | ||
|
|
a325883b62 | ||
|
|
5c7c13d76a | ||
|
|
06cee3f03e | ||
|
|
ec0d88cf1b | ||
|
|
eca37f934c | ||
|
|
18cf749ad9 | ||
|
|
1febbc869f | ||
|
|
ea49097ab3 | ||
|
|
1dcc69db39 | ||
|
|
fc3ac2eb33 | ||
|
|
0289aba113 | ||
|
|
15f076f7d6 | ||
|
|
63e2ba799d | ||
|
|
1ff8a2aaf4 | ||
|
|
980340546a | ||
|
|
ebde5a1cb7 | ||
|
|
ffa8c3e5bf | ||
|
|
5a8641660c | ||
|
|
36641d73a6 | ||
|
|
eac29cd0b6 | ||
|
|
e8a5f59b4c | ||
|
|
7526714b4a | ||
|
|
2ab78022f5 | ||
|
|
363bf0ea38 | ||
|
|
d465639d2a | ||
|
|
0790b30b5d |
@@ -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 --depth 1 --recursive monero
|
||||
- TOR_BIN="/usr/local/tor/bin/tor" 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 --depth 1 --recursive monero
|
||||
- PATH="/mxe/usr/bin/:$PATH" TOR_BIN="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.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,9 +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: 91e773a27d27f29ea62f5df500664b733df641b7c31202c8e5558174fd046fba
|
||||
hmac: f16a0379280e2e89987930d635ec6fb938d67732fdaf4ddc488f2a9db64bda2c
|
||||
|
||||
...
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,6 +10,44 @@ Static builds via Docker are done in 3 steps:
|
||||
2. Creating a base Docker image
|
||||
3. Using the base image to compile a build
|
||||
|
||||
### Linux (reproducible)
|
||||
|
||||
The docker image for reproducible Linux static builds uses Ubuntu 16.04 and compiles the required libraries statically
|
||||
so that the resulting Feather binary is static. For more information, check the Dockerfile: `Dockerfile`.
|
||||
|
||||
#### 1. Clone
|
||||
|
||||
```bash
|
||||
git clone --branch master --recursive https://git.wownero.com/feather/feather.git
|
||||
cd feather
|
||||
```
|
||||
|
||||
Replace `master` with the desired version tag (e.g. `beta-1`) to build the release binary.
|
||||
|
||||
#### 2. Base image
|
||||
|
||||
```bash
|
||||
docker build --tag feather:linux --build-arg THREADS=4 .
|
||||
```
|
||||
|
||||
Building the base image takes a while. You only need to build the base image once.
|
||||
|
||||
#### 3. Build
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $PWD:/feather --env OPENSSL_ROOT_DIR=/usr/local/openssl/ -w /feather feather:linux sh -c 'TOR_BIN="/usr/local/tor/bin/tor" make release-static -j4'
|
||||
```
|
||||
|
||||
If you're re-running a build make sure to `rm -rf build/` first.
|
||||
|
||||
The resulting binary can be found in `build/bin/feather`.
|
||||
|
||||
Hashes for tagged commits should match:
|
||||
|
||||
```
|
||||
beta-1: d1a52e3bac1abbae4adda1fc88cb2a7a06fbd61085868421897c6a4f3f4eb091 feather
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
The docker image for Windows static compiles uses Ubuntu 18.04 and installs [mxe](https://mxe.cc) from [our git](https://git.wownero.com/feather/mxe/src/branch/feather-patch),
|
||||
@@ -35,45 +73,12 @@ 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'
|
||||
```
|
||||
|
||||
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
|
||||
|
||||
The resulting binary can be found in `build/bin/feather.exe`.
|
||||
|
||||
### Linux
|
||||
|
||||
The docker image for Linux static compiles uses Ubuntu 18.04 and compiles the required libraries statically so that
|
||||
the resulting Feather binary is static. It comes with OpenSSL 1.1.1g, Qt 5.15.0 (OpenGL disabled). For more information,
|
||||
check the Dockerfile: `Dockerfile`.
|
||||
|
||||
#### 1. Clone
|
||||
|
||||
```bash
|
||||
git clone --recursive https://git.wownero.com/feather/feather.git
|
||||
cd feather
|
||||
```
|
||||
|
||||
#### 2. Base image
|
||||
|
||||
Warning: Building the base image takes a while, go prepare some dinner.
|
||||
|
||||
```bash
|
||||
docker build --tag feather:linux --build-arg THREADS=8 .
|
||||
```
|
||||
|
||||
Note: You only need to build the base image once.
|
||||
|
||||
#### 3. Build
|
||||
|
||||
```bash
|
||||
docker run --env OPENSSL_ROOT_DIR=/usr/local/openssl/ --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:linux sh -c 'make release-static -j8'
|
||||
docker run --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:win /bin/bash -c 'PATH="/mxe/usr/bin/:$PATH" TOR_BIN="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" make windows-mxe-release -j8'
|
||||
```
|
||||
|
||||
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
|
||||
|
||||
The resulting binary can be found in `build/bin/feather`.
|
||||
The resulting binary can be found in `build/bin/feather.exe`.
|
||||
|
||||
## macOS
|
||||
|
||||
@@ -98,4 +103,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.
|
||||
|
||||
@@ -7,11 +7,13 @@ 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-3")
|
||||
|
||||
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(XMRIG "Include XMRig module" ON)
|
||||
option(TOR_BIN "Path to Tor binary to embed inside Feather" OFF)
|
||||
|
||||
option(STATIC "Link libraries statically, requires static Qt")
|
||||
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
|
||||
option(DONATE_BEG "Prompt donation window every once in a while" ON)
|
||||
@@ -28,7 +30,7 @@ if(DEBUG)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
endif()
|
||||
|
||||
set(MONERO_HEAD "a1404e92cb439ba0f120e7c4a579ed0b9a0372a4")
|
||||
set(MONERO_HEAD "85b0b4f73aa6114e3ff91207aa94ad2a15c939a2")
|
||||
set(BUILD_GUI_DEPS ON)
|
||||
set(ARCH "x86-64")
|
||||
set(BUILD_64 ON)
|
||||
@@ -157,7 +159,11 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
|
||||
locale)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_SKIP_RPATH ON)
|
||||
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}")
|
||||
@@ -170,47 +176,30 @@ 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(BUILD_TOR AND APPLE)
|
||||
execute_process(COMMAND bash -c "touch ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
|
||||
ENDIF()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(TOR_LIB "libtorsocks.so")
|
||||
elseif(APPLE)
|
||||
set(TOR_LIB "libtorsocks.dylib")
|
||||
if("$ENV{DRONE}" STREQUAL "true")
|
||||
message(STATUS "We are inside a static compile with Drone CI")
|
||||
endif()
|
||||
|
||||
if("$ENV{DRONE}" STREQUAL "true" AND APPLE)
|
||||
message(STATUS "We are inside a static compile with Drone CI")
|
||||
# @TODO: taken from Tor Browser official release for now
|
||||
execute_process(COMMAND bash -c "cp ~/tor/libevent-2.1.7.dylib ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
|
||||
execute_process(COMMAND bash -c "cp ~/tor/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
|
||||
elseif("$ENV{DRONE}" STREQUAL "true" AND BUILD_TOR)
|
||||
message(STATUS "We are inside a static compile with Drone CI")
|
||||
if(MINGW)
|
||||
execute_process(COMMAND bash -c "cp /mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe ${CMAKE_SOURCE_DIR}/src/tor/tor.exe")
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
execute_process(COMMAND bash -c "cp /usr/local/tor/bin/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
|
||||
execute_process(COMMAND bash -c "cp /usr/local/torsocks/lib/torsocks/* ${CMAKE_SOURCE_DIR}/src/tor/")
|
||||
# To build Feather with embedded (and static) Tor, pass CMake -DTOR_BIN=/path/to/tor
|
||||
if(TOR_BIN)
|
||||
if(APPLE)
|
||||
execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
|
||||
endif()
|
||||
|
||||
# on the buildbot Tor is baked into the image
|
||||
# - linux: See `Dockerfile`
|
||||
# - windows: https://github.com/mxe/mxe/blob/1024dc7d2db5eb7d5d3c64a2c12b5f592572f1ce/plugins/apps/tor.mk
|
||||
# - macos: taken from Tor Browser official release
|
||||
set(TOR_COPY_CMD "cp -u ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
|
||||
message(STATUS "${TOR_COPY_CMD}")
|
||||
execute_process(COMMAND bash -c "${TOR_COPY_CMD}" RESULT_VARIABLE ret)
|
||||
if(ret EQUAL "1")
|
||||
message(FATAL_ERROR "Tor copy failure: ${TOR_COPY_CMD}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Embedding Tor binary at ${TOR_BIN}")
|
||||
else()
|
||||
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")
|
||||
endif()
|
||||
message(STATUS "Skipping Tor inclusion because -DTOR_BIN=Off")
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
@@ -358,4 +347,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)
|
||||
|
||||
@@ -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 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 && \
|
||||
tar -xzf openssl-1.1.1g.tar.gz && \
|
||||
cd openssl-1.1.1g && \
|
||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./config no-shared no-zlib-dynamic --prefix=/usr/local/openssl && \
|
||||
RUN wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \
|
||||
echo "e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242 openssl-1.1.1i.tar.gz" | sha256sum -c && \
|
||||
tar -xzf openssl-1.1.1i.tar.gz && \
|
||||
rm openssl-1.1.1i.tar.gz && \
|
||||
cd openssl-1.1.1i && \
|
||||
./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,13 @@ 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,7 +42,8 @@ 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
|
||||
- `-DXMRIG=OFF` - disable XMRig feature
|
||||
- `-DTOR_BIN=/path/to/tor` - Embed a Tor executable inside Feather
|
||||
- `-DDONATE_BEG=OFF` - disable the dreaded donate requests
|
||||
|
||||
And:
|
||||
|
||||
@@ -30,7 +30,9 @@ CMAKEFLAGS = \
|
||||
-DARCH=x86_64 \
|
||||
-DBUILD_64=On \
|
||||
-DBUILD_TESTS=Off \
|
||||
-DXMRTO=ON \
|
||||
-DXMRTO=On \
|
||||
-DXMRIG=On \
|
||||
-DTOR_BIN=Off \
|
||||
-DCMAKE_CXX_STANDARD=11 \
|
||||
-DCMAKE_VERBOSE_MAKEFILE=On \
|
||||
-DINSTALL_VENDORED_LIBUNBOUND=Off \
|
||||
@@ -40,29 +42,29 @@ CMAKEFLAGS = \
|
||||
$(CMAKEFLAGS_EXTRA)
|
||||
|
||||
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
|
||||
release-static: CMAKEFLAGS += -DBUILD_TOR=On
|
||||
release-static: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
|
||||
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
|
||||
release-static:
|
||||
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_BIN=$(or ${TOR_BIN},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_BIN=$(or ${TOR_BIN},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_BIN=$(or ${TOR_BIN},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)
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
# Maintainer: wowario <wowario[at]protonmail[dot]com>
|
||||
# Contributor: wowario <wowario[at]protonmail[dot]com>
|
||||
|
||||
pkgbase=('monero-feather-git')
|
||||
pkgname=('monero-feather-git')
|
||||
pkgver=v0.1.0.0.cd1cd5cb75
|
||||
pkgname='monero-feather-git'
|
||||
pkgver=0.1.0.925ef5683
|
||||
pkgrel=1
|
||||
pkgdesc="a free Monero desktop wallet"
|
||||
pkgdesc='a free Monero desktop wallet'
|
||||
license=('BSD')
|
||||
arch=('x86_64')
|
||||
url="https://featherwallet.org"
|
||||
depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'zeromq' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc'
|
||||
'libgcrypt' 'qrencode' 'ccache' 'libsodium' 'libpgm' 'expat' 'base-devel' 'qt5-base')
|
||||
depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc' 'libgcrypt' 'qrencode' 'libsodium' 'libpgm' 'expat' 'qt5-base' 'qt5-websockets' 'tor')
|
||||
makedepends=('git' 'cmake' 'boost')
|
||||
provides=('monero-feather-git')
|
||||
|
||||
source=("${pkgname}"::"git+https://git.wownero.com/feather/feather")
|
||||
|
||||
sha256sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/$pkgname"
|
||||
git describe --long --tags | sed 's/\([^-]*-\)g/r\1/;s/-/./g'
|
||||
cd "${srcdir}/${pkgname}"
|
||||
printf "%s.%s" "$(git describe --tags --abbrev=0)" "$(git rev-parse --short=9 HEAD)"
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname}"
|
||||
mkdir build && cd build && cmake .. && make release-static -j2
|
||||
git submodule update --init --recursive
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
}
|
||||
|
||||
package_feather-git() {
|
||||
package_monero-feather-git() {
|
||||
install -Dm644 "${srcdir}/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
install -Dm755 "${srcdir}/${pkgname}/build/bin/feather" "${pkgdir}/usr/bin/feather"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -42,14 +42,12 @@ file(GLOB SOURCE_FILES
|
||||
"dialog/*.cpp"
|
||||
)
|
||||
|
||||
if((APPLE AND BUILD_TOR) OR (APPLE AND "$ENV{DRONE}" STREQUAL "true"))
|
||||
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_BIN)
|
||||
if(APPLE)
|
||||
set(ASSETS_TOR "assets_tor_macos.qrc")
|
||||
else()
|
||||
set(ASSETS_TOR "assets_tor.qrc")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(EXECUTABLE_FLAG)
|
||||
@@ -74,8 +72,8 @@ endif()
|
||||
add_executable(feather ${EXECUTABLE_FLAG} main.cpp
|
||||
${SOURCE_FILES}
|
||||
${RESOURCES}
|
||||
${ASSETS_OS}
|
||||
)
|
||||
${ASSETS_TOR}
|
||||
)
|
||||
|
||||
# mac os bundle
|
||||
set_target_properties(feather PROPERTIES
|
||||
@@ -122,12 +120,16 @@ if(DONATE_BEG)
|
||||
target_compile_definitions(feather PRIVATE DONATE_BEG=1)
|
||||
endif()
|
||||
|
||||
if(BUILD_TOR)
|
||||
target_compile_definitions(feather PRIVATE BUILD_TOR=1)
|
||||
if(XMRTO)
|
||||
target_compile_definitions(feather PRIVATE HAS_XMRTO=1)
|
||||
endif()
|
||||
|
||||
if(XMRTO)
|
||||
target_compile_definitions(feather PRIVATE XMRTO=1)
|
||||
if(TOR_BIN)
|
||||
target_compile_definitions(feather PRIVATE HAS_TOR_BIN=1)
|
||||
endif()
|
||||
|
||||
if(XMRIG)
|
||||
target_compile_definitions(feather PRIVATE HAS_XMRIG=1)
|
||||
endif()
|
||||
|
||||
if(HAVE_SYS_PRCTL_H)
|
||||
@@ -194,6 +196,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
|
||||
|
||||
@@ -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;
|
||||
@@ -36,6 +37,7 @@ WalletKeysFilesModel *AppContext::wallets = nullptr;
|
||||
TxFiatHistory *AppContext::txFiatHistory = nullptr;
|
||||
double AppContext::balance = 0;
|
||||
QMap<QString, QString> AppContext::txDescriptionCache;
|
||||
QMap<QString, QString> AppContext::txCache;
|
||||
|
||||
AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
this->network = new QNetworkAccessManager();
|
||||
@@ -78,13 +80,19 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
this->accountName = Utils::getUnixAccountName();
|
||||
this->homeDir = QDir::homePath();
|
||||
|
||||
QString walletDir = config()->get(Config::walletDirectory).toString();
|
||||
if (walletDir.isEmpty()) {
|
||||
#if defined(Q_OS_LINUX) or defined(Q_OS_MAC)
|
||||
this->defaultWalletDir = QString("%1/Monero/wallets").arg(this->configRoot);
|
||||
this->defaultWalletDirRoot = QString("%1/Monero").arg(this->configRoot);
|
||||
this->defaultWalletDir = QString("%1/Monero/wallets").arg(this->configRoot);
|
||||
this->defaultWalletDirRoot = QString("%1/Monero").arg(this->configRoot);
|
||||
#elif defined(Q_OS_WIN)
|
||||
this->defaultWalletDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Monero";
|
||||
this->defaultWalletDirRoot = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
this->defaultWalletDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Monero";
|
||||
this->defaultWalletDirRoot = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
#endif
|
||||
} else {
|
||||
this->defaultWalletDir = walletDir;
|
||||
this->defaultWalletDirRoot = walletDir;
|
||||
}
|
||||
|
||||
// Create wallet dirs
|
||||
if (!QDir().mkpath(defaultWalletDir))
|
||||
@@ -95,7 +103,6 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
if(!this->configDirectory.endsWith('/'))
|
||||
this->configDirectory = QString("%1/").arg(this->configDirectory);
|
||||
#endif
|
||||
this->sorry();
|
||||
|
||||
// Config
|
||||
createConfigDirectory(this->configDirectory);
|
||||
@@ -112,7 +119,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);
|
||||
@@ -134,11 +140,11 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
auto genesis_timestamp = this->restoreHeights[NetworkType::Type::MAINNET]->data.firstKey();
|
||||
AppContext::txFiatHistory = new TxFiatHistory(genesis_timestamp, this->configDirectory);
|
||||
connect(this->ws, &WSClient::connectionEstablished, AppContext::txFiatHistory, &TxFiatHistory::onUpdateDatabase);
|
||||
connect(AppContext::txFiatHistory, &TxFiatHistory::requestYear, [=](unsigned int year){
|
||||
connect(AppContext::txFiatHistory, &TxFiatHistory::requestYear, [=](int year){
|
||||
QByteArray data = QString(R"({"cmd": "txFiatHistory", "data": {"year": %1}})").arg(year).toUtf8();
|
||||
this->ws->sendMsg(data);
|
||||
});
|
||||
connect(AppContext::txFiatHistory, &TxFiatHistory::requestYearMonth, [=](unsigned int year, unsigned int month) {
|
||||
connect(AppContext::txFiatHistory, &TxFiatHistory::requestYearMonth, [=](int year, int month) {
|
||||
QByteArray data = QString(R"({"cmd": "txFiatHistory", "data": {"year": %1, "month": %2}})").arg(year).arg(month).toUtf8();
|
||||
this->ws->sendMsg(data);
|
||||
});
|
||||
@@ -147,10 +153,16 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
AppContext::prices = new Prices();
|
||||
|
||||
// xmr.to
|
||||
#if defined(XMRTO)
|
||||
#ifdef HAS_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();
|
||||
@@ -173,7 +185,7 @@ void AppContext::initTor() {
|
||||
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"))
|
||||
@@ -188,7 +200,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);
|
||||
}
|
||||
@@ -227,8 +239,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;
|
||||
@@ -237,7 +249,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);
|
||||
@@ -253,7 +265,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
|
||||
@@ -276,6 +287,10 @@ void AppContext::onOpenWallet(const QString &path, const QString &password){
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.isEmpty()) {
|
||||
this->walletPassword = "";
|
||||
}
|
||||
|
||||
config()->set(Config::firstRun, false);
|
||||
|
||||
this->walletPath = path;
|
||||
@@ -310,13 +325,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);
|
||||
@@ -330,9 +346,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
|
||||
@@ -341,6 +360,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) {
|
||||
@@ -353,22 +384,22 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
|
||||
auto changed = false;
|
||||
|
||||
if(!this->heights.contains("mainnet")) {
|
||||
this->heights["mainnet"] = (unsigned int) mainnet;
|
||||
this->heights["mainnet"] = mainnet;
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
if (mainnet > this->heights["mainnet"]) {
|
||||
this->heights["mainnet"] = (unsigned int) mainnet;
|
||||
this->heights["mainnet"] = mainnet;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if(!this->heights.contains("stagenet")) {
|
||||
this->heights["stagenet"] = (unsigned int) stagenet;
|
||||
this->heights["stagenet"] = stagenet;
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
if (stagenet > this->heights["stagenet"]) {
|
||||
this->heights["stagenet"] = (unsigned int) stagenet;
|
||||
this->heights["stagenet"] = stagenet;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -380,7 +411,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);
|
||||
@@ -390,7 +425,7 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
|
||||
QJsonObject fiat_rates = msg.value("data").toObject();
|
||||
AppContext::prices->fiatPricesReceived(fiat_rates);
|
||||
}
|
||||
#if defined(XMRTO)
|
||||
#if defined(HAS_XMRTO)
|
||||
else if(cmd == "xmrto_rates") {
|
||||
auto xmr_rates = msg.value("data").toObject();
|
||||
this->XMRTo->onRatesReceived(xmr_rates);
|
||||
@@ -434,7 +469,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);
|
||||
@@ -494,31 +530,16 @@ 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_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});
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,6 +562,43 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
|
||||
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;
|
||||
@@ -553,7 +611,7 @@ void AppContext::initRestoreHeights() {
|
||||
restoreHeights[NetworkType::MAINNET] = RestoreHeightLookup::fromFile(":/assets/restore_heights_monero_mainnet.txt", NetworkType::MAINNET);
|
||||
}
|
||||
|
||||
void AppContext::onSetRestoreHeight(unsigned int height){
|
||||
void AppContext::onSetRestoreHeight(quint64 height){
|
||||
auto seed = this->currentWallet->getCacheAttribute("feather.seed");
|
||||
if(!seed.isEmpty()) {
|
||||
const auto msg = "This wallet has a 14 word mnemonic seed which has the restore height embedded.";
|
||||
@@ -562,7 +620,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();
|
||||
@@ -614,8 +672,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)
|
||||
@@ -627,15 +686,6 @@ void AppContext::donateBeg() {
|
||||
config()->set(Config::donateBeg, donationCounter);
|
||||
}
|
||||
|
||||
void AppContext::sorry() {
|
||||
auto msg = "Unable to start Feather, error code 0xd34db33f. If this problem "
|
||||
"persists, please contact Technical Support.";
|
||||
QStringList paths = {"C:\\ProgramData\\ryo", this->homeDir + "/.ryo"};
|
||||
for(const QString &ryo: paths)
|
||||
if(Utils::dirExists(ryo))
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
AppContext::~AppContext() {
|
||||
this->walletClose(false);
|
||||
}
|
||||
@@ -643,19 +693,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()) {
|
||||
@@ -673,13 +723,16 @@ void AppContext::onWalletUpdate() {
|
||||
this->storeWallet();
|
||||
}
|
||||
|
||||
void AppContext::onWalletRefreshed() {
|
||||
void AppContext::onWalletRefreshed(bool success) {
|
||||
if (!this->refreshed) {
|
||||
refreshModels();
|
||||
this->refreshed = true;
|
||||
this->storeWallet();
|
||||
// store wallet immediately upon finishing synchronization
|
||||
this->currentWallet->store();
|
||||
}
|
||||
|
||||
qDebug() << "Wallet refresh status: " << success;
|
||||
|
||||
this->currentWallet->refreshHeightAsync();
|
||||
}
|
||||
|
||||
@@ -696,7 +749,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) {
|
||||
@@ -708,23 +761,28 @@ void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, q
|
||||
}
|
||||
|
||||
void AppContext::onTransactionCreated(PendingTransaction *tx, const QString &address, const QString &paymentId, quint32 mixin) {
|
||||
if(address == this->featherDonationAddress)
|
||||
this->featherDonationSending = true;
|
||||
if(address == this->donationAddress)
|
||||
this->donationSending = true;
|
||||
|
||||
// Let UI know that the transaction was constructed
|
||||
emit endTransaction();
|
||||
|
||||
// tx created, but not sent yet. ask user to verify first.
|
||||
emit createTransactionSuccess(tx, address, mixin);
|
||||
emit endTransaction();
|
||||
}
|
||||
|
||||
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
|
||||
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->storeWallet();
|
||||
|
||||
// Store wallet immediately so we don't risk losing tx key if wallet crashes
|
||||
this->currentWallet->store();
|
||||
|
||||
emit transactionCommitted(status, tx, txid);
|
||||
|
||||
// this tx was a donation to Feather, stop our nagging
|
||||
if(this->featherDonationSending) {
|
||||
this->featherDonationSending = false;
|
||||
if(this->donationSending) {
|
||||
this->donationSending = false;
|
||||
config()->set(Config::donateBeg, -1);
|
||||
}
|
||||
}
|
||||
@@ -741,16 +799,14 @@ void AppContext::storeWallet() {
|
||||
}
|
||||
|
||||
void AppContext::updateBalance() {
|
||||
if(!this->currentWallet)
|
||||
throw std::runtime_error("this should not happen, ever");
|
||||
if (!this->currentWallet)
|
||||
return;
|
||||
|
||||
AppContext::balance = this->currentWallet->balance() / AppContext::cdiv;
|
||||
auto balance_str = QString::number(balance, 'f');
|
||||
quint64 balance_u = this->currentWallet->balance();
|
||||
AppContext::balance = balance_u / globals::cdiv;
|
||||
double spendable = this->currentWallet->unlockedBalance();
|
||||
|
||||
double unlocked = this->currentWallet->unlockedBalance() / AppContext::cdiv;
|
||||
auto unlocked_str = QString::number(unlocked, 'f');
|
||||
|
||||
emit balanceUpdated(balance, unlocked, balance_str, unlocked_str);
|
||||
emit balanceUpdated(balance_u, spendable);
|
||||
}
|
||||
|
||||
void AppContext::syncStatusUpdated(quint64 height, quint64 target) {
|
||||
|
||||
@@ -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"
|
||||
@@ -38,9 +39,11 @@ public:
|
||||
bool isTails = false;
|
||||
bool isWhonix = false;
|
||||
bool isDebug = false;
|
||||
const QString featherDonationAddress = "47ntfT2Z5384zku39pTM6hGcnLnvpRYW2Azm87GiAAH2bcTidtq278TL6HmwyL8yjMeERqGEBs3cqC8vvHPJd1cWQrGC65f";
|
||||
const int featherDonationAmount = 50; // euro
|
||||
bool featherDonationSending = false;
|
||||
|
||||
// Donation config
|
||||
const QString donationAddress = "47ntfT2Z5384zku39pTM6hGcnLnvpRYW2Azm87GiAAH2bcTidtq278TL6HmwyL8yjMeERqGEBs3cqC8vvHPJd1cWQrGC65f";
|
||||
const int donationAmount = 25; // euro
|
||||
bool donationSending = false;
|
||||
|
||||
QCommandLineParser *cmdargs;
|
||||
|
||||
@@ -56,18 +59,19 @@ public:
|
||||
|
||||
QString walletPath;
|
||||
QString walletPassword = "";
|
||||
bool walletViewOnly = false;
|
||||
NetworkType::Type networkType;
|
||||
|
||||
QString applicationPath;
|
||||
|
||||
static void createConfigDirectory(const QString &dir) ;
|
||||
|
||||
QMap<QString, unsigned int> heights;
|
||||
QMap<QString, int> heights;
|
||||
QMap<NetworkType::Type, RestoreHeightLookup*> restoreHeights;
|
||||
const unsigned int kdfRounds = 1;
|
||||
const quint64 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,19 +80,22 @@ public:
|
||||
Tor *tor;
|
||||
WSClient *ws;
|
||||
XmrTo *XMRTo;
|
||||
XmRig *XMRig;
|
||||
Nodes *nodes;
|
||||
static Prices *prices;
|
||||
static WalletKeysFilesModel *wallets;
|
||||
static double balance;
|
||||
static QMap<QString, QString> txDescriptionCache;
|
||||
static QMap<QString, QString> txCache;
|
||||
static TxFiatHistory *txFiatHistory;
|
||||
|
||||
// libwalletqt
|
||||
unsigned int blockHeight = 0;
|
||||
bool refreshed = false;
|
||||
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 +105,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);
|
||||
@@ -107,7 +115,7 @@ public slots:
|
||||
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const;
|
||||
void onCreateTransactionError(const QString &msg);
|
||||
void onOpenAliasResolve(const QString &openAlias);
|
||||
void onSetRestoreHeight(unsigned int height);
|
||||
void onSetRestoreHeight(quint64 height);
|
||||
void onPreferredFiatCurrencyChanged(const QString &symbol);
|
||||
|
||||
private slots:
|
||||
@@ -120,7 +128,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);
|
||||
@@ -129,18 +137,18 @@ private slots:
|
||||
void onConnectionStatusChanged(int status);
|
||||
|
||||
signals:
|
||||
void balanceUpdated(double balance, double unlocked, QString balance_str, QString unlocked_str);
|
||||
void balanceUpdated(quint64 balance, quint64 spendable);
|
||||
void blockchainSync(int height, int target);
|
||||
void refreshSync(int height, int target);
|
||||
void synchronized();
|
||||
void blockHeightWSUpdated(QMap<QString, unsigned int> heights);
|
||||
void blockHeightWSUpdated(QMap<QString, int> heights);
|
||||
void walletSynchronized();
|
||||
void walletOpened();
|
||||
void walletClosed();
|
||||
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,24 +157,25 @@ 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);
|
||||
void openAliasResolved(const QString &address, const QString &openAlias);
|
||||
void setRestoreHeightError(const QString &msg);
|
||||
void customRestoreHeightSet(unsigned int height);
|
||||
void customRestoreHeightSet(int height);
|
||||
void closeApplication();
|
||||
void donationNag();
|
||||
void initiateTransaction();
|
||||
void endTransaction();
|
||||
void walletClosing();
|
||||
void setTitle(const QString &title); // set window title
|
||||
|
||||
private:
|
||||
void sorry();
|
||||
const unsigned int m_donationBoundary = 15;
|
||||
const int m_donationBoundary = 15;
|
||||
UtilsNetworking *m_utilsNetworkingNodes;
|
||||
QTimer *m_storeTimer = new QTimer(this);
|
||||
QUrl m_wsUrl = QUrl(QStringLiteral("ws://dtg2clrd6iand4mwp2x6nhbqd3nqbxlbiw65f6vkwmmutxy2sijsnjyd.onion/ws"));
|
||||
QUrl m_wsUrl = QUrl(QStringLiteral("ws://7e6egbawekbkxzkv4244pqeqgoo4axko2imgjbedwnn6s5yb6b7oliqd.onion/ws"));
|
||||
};
|
||||
|
||||
#endif //FEATHER_APPCONTEXT_H
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<file>assets/images/appicons/128x128.png</file>
|
||||
<file>assets/images/appicons/256x256.png</file>
|
||||
<file>assets/images/arrow.svg</file>
|
||||
<file>assets/images/banners/1.png</file>
|
||||
<file>assets/images/banners/2.png</file>
|
||||
<file>assets/images/banners/3.png</file>
|
||||
<file>assets/images/bitcoin.png</file>
|
||||
<file>assets/images/camera_dark.png</file>
|
||||
<file>assets/images/camera_white.png</file>
|
||||
@@ -23,6 +26,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 +34,12 @@
|
||||
<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/gnome-calc.png</file>
|
||||
<file>assets/images/history.png</file>
|
||||
<file>assets/images/info.png</file>
|
||||
<file>assets/images/key.png</file>
|
||||
@@ -41,12 +47,13 @@
|
||||
<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/mining.png</file>
|
||||
<file>assets/images/network.png</file>
|
||||
<file>assets/images/offline_tx.png</file>
|
||||
<file>assets/images/person.svg</file>
|
||||
<file>assets/images/photos/1.png</file>
|
||||
<file>assets/images/preferences.png</file>
|
||||
<file>assets/images/preferences.svg</file>
|
||||
<file>assets/images/qrcode.png</file>
|
||||
@@ -91,10 +98,11 @@
|
||||
<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>
|
||||
<file>assets/restore_heights_monero_stagenet.txt</file>
|
||||
<file>assets/user_agents.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
The wallet UI is heavily inspired by Electrum. We would like to recognize Thomas Voegtlin for his pioneering work on Bitcoin.
|
||||
|
||||
Feather uses monero-seed written by Tevador, for 14 word mnemonic seeds.
|
||||
|
||||
Initial CMake support for the Monero GUI was coded by TheCharlatan/xiphon.
|
||||
Wizard banner art was adapted from a paper wallet design by the themonera (themonera.art).
|
||||
|
||||
The wallet UI is heavily inspired by Electrum. We would like to recognize Thomas Voegtlin for his pioneering work on Bitcoin.
|
||||
Initial CMake support for the Monero GUI was coded by TheCharlatan/xiphon.
|
||||
|
||||
Huge thanks to nioc, fluffypony, wowario, thrmo for help during development.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
@@ -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 |
@@ -1,6 +0,0 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/">
|
||||
<file>tor/tor</file>
|
||||
<file>tor/libevent-2.1.7.dylib</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/">
|
||||
<file>tor/tor</file>
|
||||
<file>assets/exec/tor</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -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>
|
||||
@@ -1,5 +0,0 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/">
|
||||
<file>tor/tor.exe</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
#include "utils/utils.h"
|
||||
#include "dialog/outputinfodialog.h"
|
||||
#include "dialog/outputsweepdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDebug>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
|
||||
CoinsWidget::CoinsWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
@@ -21,6 +23,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);
|
||||
@@ -34,20 +37,21 @@ CoinsWidget::CoinsWidget(QWidget *parent)
|
||||
m_copyMenu->addAction("Key Image", this, [this]{copy(copyField::KeyImage);});
|
||||
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
|
||||
m_copyMenu->addAction("Address", this, [this]{copy(copyField::Address);});
|
||||
m_copyMenu->addAction("Label", this, [this]{copy(copyField::Label);});
|
||||
m_copyMenu->addAction("Height", this, [this]{copy(copyField::Height);});
|
||||
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
|
||||
|
||||
// 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);
|
||||
@@ -63,13 +67,19 @@ CoinsWidget::CoinsWidget(QWidget *parent)
|
||||
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);
|
||||
@@ -103,10 +113,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);
|
||||
}
|
||||
|
||||
@@ -183,7 +198,7 @@ void CoinsWidget::onSweepOutput() {
|
||||
qCritical() << "key image: " << keyImage;
|
||||
|
||||
if (!keyImageKnown) {
|
||||
Utils::showMessageBox("Unable to sweep output", "Unable to sweep output: key image unknown", true);
|
||||
QMessageBox::warning(this, "Unable to sweep output", "Unable to sweep output: key image unknown");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -194,6 +209,7 @@ void CoinsWidget::onSweepOutput() {
|
||||
qCritical() << "key image: " << keyImage;
|
||||
|
||||
emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs());
|
||||
dialog->deleteLater();
|
||||
}
|
||||
|
||||
void CoinsWidget::copy(copyField field) {
|
||||
@@ -215,6 +231,9 @@ void CoinsWidget::copy(copyField field) {
|
||||
case Address:
|
||||
data = c.address();
|
||||
break;
|
||||
case Label:
|
||||
data = c.addressLabel();
|
||||
break;
|
||||
case Height:
|
||||
data = QString::number(c.blockHeight());
|
||||
break;
|
||||
|
||||
@@ -48,6 +48,7 @@ private:
|
||||
KeyImage,
|
||||
TxID,
|
||||
Address,
|
||||
Label,
|
||||
Height,
|
||||
Amount
|
||||
};
|
||||
@@ -67,6 +68,7 @@ private:
|
||||
Coins *m_coins;
|
||||
CoinsModel * m_model;
|
||||
CoinsProxyModel * m_proxyModel;
|
||||
AppContext *m_ctx;
|
||||
|
||||
void showContextMenu(const QPoint & point);
|
||||
void copy(copyField field);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
#include "ui_contactswidget.h"
|
||||
#include "dialog/contactsdialog.h"
|
||||
#include "model/ModelUtils.h"
|
||||
#include "utils/utils.h"
|
||||
#include "mainwindow.h"
|
||||
#include "libwalletqt/AddressBook.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDebug>
|
||||
#include <QKeyEvent>
|
||||
#include <QMessageBox>
|
||||
|
||||
ContactsWidget::ContactsWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::ContactsWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
m_ctx = MainWindow::getContext();
|
||||
|
||||
// header context menu
|
||||
ui->contacts->header()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
@@ -28,15 +28,16 @@ ContactsWidget::ContactsWidget(QWidget *parent) :
|
||||
// context menu
|
||||
ui->contacts->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_contextMenu = new QMenu(ui->contacts);
|
||||
m_contextMenu->addAction(QIcon(":/assets/images/person.svg"), "New contact", this, &ContactsWidget::newContact);
|
||||
|
||||
m_contextMenu->addAction(QIcon(":/assets/images/person.svg"), "New contact", [this]{
|
||||
this->newContact();
|
||||
});
|
||||
|
||||
// row context menu
|
||||
m_rowMenu = new QMenu(ui->contacts);
|
||||
m_rowMenu->addAction(QIcon(":/assets/images/copy.png"), "Copy address", this, &ContactsWidget::copyAddress);
|
||||
m_rowMenu->addAction(QIcon(":/assets/images/copy.png"), "Copy name", this, &ContactsWidget::copyName);
|
||||
m_rowMenu->addAction(QIcon(":/assets/images/appicons/128x128.png"), "Pay to", this, &ContactsWidget::payTo);
|
||||
m_deleteEntryAction = m_rowMenu->addAction("Delete", this, &ContactsWidget::deleteContact);
|
||||
m_rowMenu->addAction("Pay to", this, &ContactsWidget::payTo);
|
||||
m_rowMenu->addAction("Delete", this, &ContactsWidget::deleteContact);
|
||||
|
||||
connect(ui->contacts, &QTreeView::customContextMenuRequested, [=](const QPoint & point){
|
||||
QModelIndex index = ui->contacts->indexAt(point);
|
||||
@@ -95,16 +96,44 @@ void ContactsWidget::showHeaderMenu(const QPoint& position)
|
||||
m_headerMenu->exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void ContactsWidget::newContact()
|
||||
void ContactsWidget::newContact(QString address, QString name)
|
||||
{
|
||||
auto * dialog = new ContactsDialog(this);
|
||||
auto * dialog = new ContactsDialog(this, address, name);
|
||||
int ret = dialog->exec();
|
||||
if (!ret) return;
|
||||
|
||||
QString address = dialog->getAddress();
|
||||
QString name = dialog->getName();
|
||||
address = dialog->getAddress();
|
||||
name = dialog->getName();
|
||||
|
||||
emit addContact(address, name);
|
||||
bool addressValid = WalletManager::addressValid(address, m_ctx->currentWallet->nettype());
|
||||
if (!addressValid) {
|
||||
QMessageBox::warning(this, "Invalid address", "Invalid address");
|
||||
return;
|
||||
}
|
||||
|
||||
int num_addresses = m_ctx->currentWallet->addressBook()->count();
|
||||
QString address_entry;
|
||||
QString name_entry;
|
||||
for (int i=0; i<num_addresses; i++) {
|
||||
m_ctx->currentWallet->addressBook()->getRow(i, [&address_entry, &name_entry](const AddressBookInfo &entry){
|
||||
address_entry = entry.address();
|
||||
name_entry = entry.description();
|
||||
});
|
||||
|
||||
if (address == address_entry) {
|
||||
QMessageBox::warning(this, "Unable to add contact", "Duplicate address");
|
||||
ui->contacts->setCurrentIndex(m_model->index(i,0)); // Highlight duplicate address
|
||||
return;
|
||||
}
|
||||
if (name == name_entry) {
|
||||
QMessageBox::warning(this, "Unable to add contact", "Duplicate label");
|
||||
this->newContact(address, name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_ctx->currentWallet->addressBook()->addRow(address, "", name);
|
||||
m_ctx->storeWallet();
|
||||
}
|
||||
|
||||
void ContactsWidget::deleteContact()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "model/AddressBookModel.h"
|
||||
#include "model/AddressBookProxyModel.h"
|
||||
#include "appcontext.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMenu>
|
||||
@@ -21,29 +22,28 @@ class ContactsWidget : public QWidget
|
||||
public:
|
||||
explicit ContactsWidget(QWidget *parent = nullptr);
|
||||
void setModel(AddressBookModel * model);
|
||||
~ContactsWidget();
|
||||
~ContactsWidget() override;
|
||||
|
||||
public slots:
|
||||
void copyAddress();
|
||||
void copyName();
|
||||
void payTo();
|
||||
void newContact();
|
||||
void newContact(QString address = "", QString name = "");
|
||||
void deleteContact();
|
||||
void setShowFullAddresses(bool show);
|
||||
void setSearchFilter(const QString &filter);
|
||||
|
||||
signals:
|
||||
void addContact(QString &address, QString &name);
|
||||
void fillAddress(QString &address);
|
||||
|
||||
private slots:
|
||||
void showHeaderMenu(const QPoint& position);
|
||||
void showHeaderMenu(const QPoint &position);
|
||||
|
||||
private:
|
||||
Ui::ContactsWidget *ui;
|
||||
AppContext *m_ctx;
|
||||
|
||||
QAction *m_showFullAddressesAction;
|
||||
QAction *m_deleteEntryAction;
|
||||
QMenu *m_rowMenu;
|
||||
QMenu *m_contextMenu;
|
||||
QMenu *m_headerMenu;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020, The Monero Project.
|
||||
|
||||
#include "balancedialog.h"
|
||||
#include "ui_balancedialog.h"
|
||||
|
||||
#include "libwalletqt/WalletManager.h"
|
||||
|
||||
BalanceDialog::BalanceDialog(QWidget *parent, Wallet *wallet)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::BalanceDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->label_unconfirmed_help->setHelpText("Outputs require 10 confirmations before they become spendable. "
|
||||
"This will take 20 minutes on average.");
|
||||
|
||||
ui->label_unconfirmed->setText(WalletManager::displayAmount(wallet->balance() - wallet->unlockedBalance()));
|
||||
ui->label_spendable->setText(WalletManager::displayAmount(wallet->unlockedBalance()));
|
||||
ui->label_total->setText(WalletManager::displayAmount(wallet->balance()));
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
BalanceDialog::~BalanceDialog() {
|
||||
delete ui;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020, The Monero Project.
|
||||
|
||||
#ifndef FEATHER_BALANCEDIALOG_H
|
||||
#define FEATHER_BALANCEDIALOG_H
|
||||
|
||||
#include "libwalletqt/Wallet.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class BalanceDialog;
|
||||
}
|
||||
|
||||
class BalanceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BalanceDialog(QWidget *parent, Wallet *wallet);
|
||||
~BalanceDialog() override;
|
||||
|
||||
private:
|
||||
Ui::BalanceDialog *ui;
|
||||
};
|
||||
|
||||
#endif //FEATHER_BALANCEDIALOG_H
|
||||
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BalanceDialog</class>
|
||||
<widget class="QDialog" name="BalanceDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>405</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Balance</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="HelpLabel" name="label_unconfirmed_help">
|
||||
<property name="text">
|
||||
<string>Unconfirmed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_unconfirmed">
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_spendable_help">
|
||||
<property name="text">
|
||||
<string>Spendable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_spendable">
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Total</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_total">
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>HelpLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>components.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BalanceDialog</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>BalanceDialog</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>
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020, The Monero Project.
|
||||
|
||||
#include "broadcasttxdialog.h"
|
||||
#include "ui_broadcasttxdialog.h"
|
||||
#include "utils/nodes.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx, const QString &transactionHex)
|
||||
: QDialog(parent)
|
||||
, m_ctx(ctx)
|
||||
, ui(new Ui::BroadcastTxDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_network = new UtilsNetworking(m_ctx->network, this);
|
||||
|
||||
auto node = ctx->nodes->connection();
|
||||
m_rpc = new DaemonRpc(this, m_network, node.full);
|
||||
|
||||
connect(ui->btn_Broadcast, &QPushButton::clicked, this, &BroadcastTxDialog::broadcastTx);
|
||||
connect(ui->btn_Close, &QPushButton::clicked, this, &BroadcastTxDialog::reject);
|
||||
|
||||
connect(m_rpc, &DaemonRpc::ApiResponse, this, &BroadcastTxDialog::onApiResponse);
|
||||
|
||||
if (!transactionHex.isEmpty()) {
|
||||
ui->transaction->setPlainText(transactionHex);
|
||||
}
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
void BroadcastTxDialog::broadcastTx() {
|
||||
QString tx = ui->transaction->toPlainText();
|
||||
|
||||
QString node = [this]{
|
||||
QString node;
|
||||
if (ui->radio_useCustom->isChecked())
|
||||
node = ui->customNode->text();
|
||||
else if (ui->radio_useDefault->isChecked())
|
||||
node = m_ctx->nodes->connection().full;
|
||||
|
||||
if (!node.startsWith("http://"))
|
||||
node = QString("http://%1").arg(node);
|
||||
return node;
|
||||
}();
|
||||
|
||||
m_rpc->setDaemonAddress(node);
|
||||
m_rpc->sendRawTransaction(tx);
|
||||
}
|
||||
|
||||
void BroadcastTxDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
|
||||
if (!resp.ok) {
|
||||
QMessageBox::warning(this, "Transaction broadcast", resp.status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp.endpoint == DaemonRpc::Endpoint::SEND_RAW_TRANSACTION) {
|
||||
QMessageBox::information(this, "Transaction broadcast", "Transaction submitted successfully.\n\n"
|
||||
"If the transaction belongs to this wallet it may take several minutes before it shows up in the history tab.");
|
||||
}
|
||||
}
|
||||
|
||||
BroadcastTxDialog::~BroadcastTxDialog() {
|
||||
delete ui;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020, The Monero Project.
|
||||
|
||||
#ifndef FEATHER_BROADCASTTXDIALOG_H
|
||||
#define FEATHER_BROADCASTTXDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "appcontext.h"
|
||||
#include "utils/daemonrpc.h"
|
||||
|
||||
namespace Ui {
|
||||
class BroadcastTxDialog;
|
||||
}
|
||||
|
||||
class BroadcastTxDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BroadcastTxDialog(QWidget *parent, AppContext *ctx, const QString &transactionHex = "");
|
||||
~BroadcastTxDialog() override;
|
||||
|
||||
private slots:
|
||||
void broadcastTx();
|
||||
void onApiResponse(const DaemonRpc::DaemonResponse &resp);
|
||||
|
||||
private:
|
||||
Ui::BroadcastTxDialog *ui;
|
||||
UtilsNetworking *m_network;
|
||||
AppContext *m_ctx;
|
||||
DaemonRpc *m_rpc;
|
||||
};
|
||||
|
||||
|
||||
#endif //FEATHER_BROADCASTTXDIALOG_H
|
||||
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BroadcastTxDialog</class>
|
||||
<widget class="QDialog" name="BroadcastTxDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>797</width>
|
||||
<height>575</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Broadcast transaction</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Transaction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="transaction">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Paste hex encoded signed tx string here</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Node</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radio_useDefault">
|
||||
<property name="text">
|
||||
<string>Use currently connected node</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radio_useCustom">
|
||||
<property name="text">
|
||||
<string>Use custom node</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="customNode"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_Broadcast">
|
||||
<property name="text">
|
||||
<string>Broadcast</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_Close">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -4,13 +4,19 @@
|
||||
#include "ui_contactsdialog.h"
|
||||
#include "contactsdialog.h"
|
||||
|
||||
ContactsDialog::ContactsDialog(QWidget *parent)
|
||||
ContactsDialog::ContactsDialog(QWidget *parent, const QString &address, const QString &name)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::ContactsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setMinimumWidth(400);
|
||||
|
||||
ui->lineEdit_address->setText(address);
|
||||
ui->lineEdit_name->setText(name);
|
||||
if (!name.isEmpty()) {
|
||||
ui->lineEdit_name->setFocus();
|
||||
}
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, [&](){
|
||||
m_address = ui->lineEdit_address->text();
|
||||
m_name = ui->lineEdit_name->text();
|
||||
|
||||
@@ -15,7 +15,7 @@ class ContactsDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ContactsDialog(QWidget *parent = nullptr);
|
||||
explicit ContactsDialog(QWidget *parent = nullptr, const QString &address = "", const QString &name = "");
|
||||
~ContactsDialog() override;
|
||||
|
||||
QString getAddress();
|
||||
|
||||
@@ -12,15 +12,34 @@
|
||||
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)
|
||||
|
||||
// Special case for Tails because we know the status of the daemon by polling tails-tor-has-bootstrapped.target
|
||||
if(m_ctx->isTails) {
|
||||
if(m_ctx->tor->torConnected)
|
||||
torStatus = "Connected";
|
||||
else
|
||||
torStatus = "Disconnected";
|
||||
}
|
||||
else if(m_ctx->isTorSocks)
|
||||
torStatus = "Torsocks";
|
||||
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 +47,29 @@ 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()).remove("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_primaryOnly->setText(m_ctx->currentWallet->balance(0) == m_ctx->currentWallet->balanceAll() ? "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 +88,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);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@ public:
|
||||
private:
|
||||
QString statusToString(Wallet::ConnectionStatus status);
|
||||
void copyToClipboad();
|
||||
void updateInfo();
|
||||
|
||||
QTimer m_updateTimer;
|
||||
AppContext *m_ctx;
|
||||
|
||||
Ui::DebugInfoDialog *ui;
|
||||
};
|
||||
|
||||
@@ -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="20" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Timestamp:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<item row="20" column="1">
|
||||
<widget class="QLabel" name="label_timestamp">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
@@ -275,24 +275,58 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<item row="19" 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="19" 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="18" 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>
|
||||
<item row="17" column="1">
|
||||
<widget class="QLabel" name="label_primaryOnly">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Primary only:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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><html><head/><body><p><span style=" font-weight:600; color:#a40000;">Incorrect password, try again.</span></p></body></html></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>
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ RestoreDialog::RestoreDialog(AppContext *ctx, QWidget *parent)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int RestoreDialog::getHeight() {
|
||||
int RestoreDialog::getHeight() {
|
||||
return ui->restoreHeightWidget->getHeight();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Q_OBJECT
|
||||
public:
|
||||
explicit RestoreDialog(AppContext *ctx, QWidget *parent = nullptr);
|
||||
void initRestoreHeights(RestoreHeightLookup *lookup);
|
||||
unsigned int getHeight();
|
||||
int getHeight();
|
||||
~RestoreDialog() override;
|
||||
|
||||
signals:
|
||||
|
||||
@@ -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->frameRestoreHeight->setVisible(false);
|
||||
}
|
||||
|
||||
connect(ui->check_toggleSeedType, &QCheckBox::toggled, [this, seed_25_words, seed_14_words](bool toggled){
|
||||
this->setSeed(toggled ? seed_25_words : seed_14_words);
|
||||
ui->frameRestoreHeight->setVisible(toggled);
|
||||
});
|
||||
|
||||
ui->label_restoreHeightHelp->setHelpText("Should you restore your wallet in the future, "
|
||||
"specifying this block number will recover your wallet quicker.");
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
void SeedDialog::setSeed(const QString &seed) {
|
||||
ui->seed->setPlainText(seed);
|
||||
|
||||
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()
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>542</width>
|
||||
<height>244</height>
|
||||
<width>519</width>
|
||||
<height>330</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -34,39 +34,120 @@
|
||||
</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>100</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="QFrame" name="frameRestoreHeight">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="HelpLabel" name="label_restoreHeightHelp">
|
||||
<property name="text">
|
||||
<string>Restore height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_restoreHeight">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</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="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>warning</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<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>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
@@ -79,6 +160,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>HelpLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>components.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
||||
@@ -6,22 +6,37 @@
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
QString blockHeight = QString::number(txInfo->blockHeight());
|
||||
if (blockHeight == "0")
|
||||
blockHeight = "Unconfirmed";
|
||||
|
||||
ui->label_status->setText(QString("Status: %1 confirmations").arg(txInfo->confirmations()));
|
||||
ui->label_date->setText(QString("Date: %1").arg(txInfo->timestamp().toString("yyyy-MM-dd HH:mm")));
|
||||
ui->label_blockHeight->setText(QString("Block height: %1").arg(txInfo->blockHeight()));
|
||||
ui->label_blockHeight->setText(QString("Block height: %1").arg(blockHeight));
|
||||
|
||||
QString direction = txInfo->direction() == TransactionInfo::Direction_In ? "received" : "sent";
|
||||
ui->label_amount->setText(QString("Amount %1: %2").arg(direction, txInfo->displayAmount()));
|
||||
@@ -30,17 +45,17 @@ 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()) {
|
||||
ui->destinations->setHidden(true);
|
||||
ui->label_destinations->setHidden(true);
|
||||
ui->line_2->setHidden(true);
|
||||
ui->frameDestinations->hide();
|
||||
} else {
|
||||
ui->destinations->setText(destinations);
|
||||
}
|
||||
|
||||
ui->txProofWidget->addWidget(m_txProofWidget);
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -123,31 +132,65 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<widget class="QFrame" name="frameDestinations">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<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="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_destinations">
|
||||
<property name="text">
|
||||
<string>Destinations:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="destinations">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_destinations">
|
||||
<property name="text">
|
||||
<string>Destinations:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="destinations">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="txProofWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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,38 @@ TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const
|
||||
};
|
||||
|
||||
QString amount = WalletManager::displayAmount(tx->amount());
|
||||
QString amount_fiat = convert(tx->amount() / AppContext::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);
|
||||
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);
|
||||
ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur));
|
||||
QVector<QString> amounts = {amount, fee, total};
|
||||
int maxLength = Utils::maxLength(amounts);
|
||||
std::for_each(amounts.begin(), amounts.end(), [maxLength](QString& amount){amount = amount.rightJustified(maxLength, ' ');});
|
||||
|
||||
QString amount_fiat = convert(tx->amount() / globals::cdiv);
|
||||
QString fee_fiat = convert(tx->fee() / globals::cdiv);
|
||||
QString total_fiat = convert((tx->amount() + tx->fee()) / globals::cdiv);
|
||||
QVector<QString> amounts_fiat = {amount_fiat, fee_fiat, total_fiat};
|
||||
int maxLengthFiat = Utils::maxLength(amounts_fiat);
|
||||
std::for_each(amounts_fiat.begin(), amounts_fiat.end(), [maxLengthFiat](QString& amount){amount = amount.rightJustified(maxLengthFiat, ' ');});
|
||||
|
||||
ui->label_amount->setText(QString("%1 (%2 %3)").arg(amounts[0], amounts_fiat[0], preferredCur));
|
||||
ui->label_fee->setText(QString("%1 (%2 %3)").arg(amounts[1], amounts_fiat[1], preferredCur));
|
||||
ui->label_total->setText(QString("%1 (%2 %3)").arg(amounts[2], amounts_fiat[2], 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);
|
||||
|
||||
AppContext::txCache[tx->txid()[0]] = tx->signedTxToHex(0);
|
||||
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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>655</width>
|
||||
<width>844</width>
|
||||
<height>248</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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/>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
@@ -25,15 +25,9 @@ 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);
|
||||
|
||||
ui->history->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){
|
||||
QModelIndex index = ui->history->indexAt(point);
|
||||
if (index.isValid()) {
|
||||
m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point));
|
||||
}
|
||||
});
|
||||
connect(ui->history, &QTreeView::customContextMenuRequested, this, &HistoryWidget::showContextMenu);
|
||||
connect(ui->search, &QLineEdit::textChanged, this, &HistoryWidget::setSearchFilter);
|
||||
|
||||
connect(ui->history, &QTreeView::doubleClicked, [this](QModelIndex index){
|
||||
@@ -45,11 +39,48 @@ HistoryWidget::HistoryWidget(QWidget *parent)
|
||||
|
||||
}
|
||||
|
||||
void HistoryWidget::setModel(Coins *coins, TransactionHistoryProxyModel *model, TransactionHistory *txHistory)
|
||||
void HistoryWidget::showContextMenu(const QPoint &point) {
|
||||
QModelIndex index = ui->history->indexAt(point);
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu menu(this);
|
||||
TransactionInfo::Direction direction;
|
||||
QString txid;
|
||||
bool unconfirmed;
|
||||
m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction, &txid, &unconfirmed](TransactionInfo &tInfo) {
|
||||
direction = tInfo.direction();
|
||||
txid = tInfo.hash();
|
||||
unconfirmed = tInfo.isFailed() || tInfo.isPending();
|
||||
});
|
||||
|
||||
if (AppContext::txCache.contains(txid) && unconfirmed && direction != TransactionInfo::Direction_In) {
|
||||
menu.addAction(QIcon(":/assets/images/info.png"), "Resend transaction", this, &HistoryWidget::onResendTransaction);
|
||||
}
|
||||
|
||||
menu.addMenu(m_copyMenu);
|
||||
menu.addAction(QIcon(":/assets/images/info.png"), "Show details", this, &HistoryWidget::showTxDetails);
|
||||
menu.addAction(QIcon(":/assets/images/network.png"), "View on block explorer", this, &HistoryWidget::onViewOnBlockExplorer);
|
||||
|
||||
menu.exec(ui->history->viewport()->mapToGlobal(point));
|
||||
}
|
||||
|
||||
void HistoryWidget::onResendTransaction() {
|
||||
QModelIndex index = ui->history->currentIndex();
|
||||
QString txid;
|
||||
m_txHistory->transaction(m_model->mapToSource(index).row(), [&txid](TransactionInfo &tInfo) {
|
||||
txid = tInfo.hash();
|
||||
});
|
||||
|
||||
emit resendTransaction(txid);
|
||||
}
|
||||
|
||||
void HistoryWidget::setModel(TransactionHistoryProxyModel *model, Wallet *wallet)
|
||||
{
|
||||
m_coins = coins;
|
||||
m_model = model;
|
||||
m_txHistory = txHistory;
|
||||
m_wallet = wallet;
|
||||
m_txHistory = m_wallet->history();
|
||||
ui->history->setModel(m_model);
|
||||
|
||||
ui->history->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
@@ -66,7 +97,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();
|
||||
}
|
||||
}
|
||||
@@ -81,14 +112,6 @@ void HistoryWidget::onViewOnBlockExplorer() {
|
||||
emit viewOnBlockExplorer(txid);
|
||||
}
|
||||
|
||||
void HistoryWidget::getSpendProof() {
|
||||
QModelIndex index = ui->history->currentIndex();
|
||||
|
||||
m_txHistory->transaction(m_model->mapToSource(index).row(), [this](TransactionInfo &tInfo) {
|
||||
emit spendProof(tInfo.hash());
|
||||
});
|
||||
}
|
||||
|
||||
void HistoryWidget::setSearchText(const QString &text) {
|
||||
ui->search->setText(text);
|
||||
}
|
||||
|
||||
@@ -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,21 +22,21 @@ 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:
|
||||
void setSearchText(const QString &text);
|
||||
|
||||
signals:
|
||||
void spendProof(QString txid);
|
||||
void viewOnBlockExplorer(QString txid);
|
||||
void resendTransaction(QString txid);
|
||||
|
||||
private slots:
|
||||
void showTxDetails();
|
||||
void onViewOnBlockExplorer();
|
||||
void getSpendProof();
|
||||
void setSearchFilter(const QString &filter);
|
||||
void onResendTransaction();
|
||||
|
||||
private:
|
||||
enum copyField {
|
||||
@@ -45,13 +46,14 @@ private:
|
||||
};
|
||||
|
||||
void copy(copyField field);
|
||||
void showContextMenu(const QPoint &point);
|
||||
|
||||
Ui::HistoryWidget *ui;
|
||||
QMenu *m_contextMenu;
|
||||
QMenu *m_copyMenu;
|
||||
TransactionHistory *m_txHistory;
|
||||
TransactionHistoryProxyModel *m_model;
|
||||
Coins *m_coins;
|
||||
Wallet *m_wallet = nullptr;
|
||||
};
|
||||
|
||||
#endif //FEATHER_HISTORYWIDGET_H
|
||||
|
||||
@@ -76,6 +76,10 @@ QString CoinsInfo::address() const {
|
||||
}
|
||||
|
||||
QString CoinsInfo::addressLabel() const {
|
||||
if (m_subaddrIndex == 0) {
|
||||
return m_coinbase ? "Coinbase" : "Change";
|
||||
}
|
||||
|
||||
return m_addressLabel;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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()))
|
||||
{
|
||||
|
||||
}
|
||||