20 Commits

Author SHA1 Message Date
ardocrat eaefc58c5a wallet: fix scan 2026-05-13 17:38:07 +03:00
ardocrat 2519e68dd5 ci: build checkout submodules 2026-05-13 17:37:45 +03:00
ardocrat 73c0884f95 ci: macos runner 2026-05-08 00:10:14 +03:00
ardocrat f7b2150228 wallet: parse slatepack message at background thread 2026-05-04 14:10:52 +03:00
ardocrat 03924b5300 build: remove unused cpp flags for android 2026-05-04 01:31:35 +03:00
ardocrat a479189135 tx: show message input after copy/share if finalization is needed 2026-05-03 23:34:45 +03:00
ardocrat e691a7b02d ci: fix changelog, update wix upgradecode on every build 2026-05-03 23:05:26 +03:00
ardocrat f2b79cd70d build: add rustfmt hook and config 2026-05-03 10:05:03 +03:00
ardocrat f20d1ee2c2 node: use git hash for user agent 2026-05-02 23:34:42 +03:00
ardocrat 534c4cc86a node: update user-agent, include last fixes for peers from PRs 2026-05-01 12:50:50 +03:00
ardocrat 558ac034b2 txs: fix save with new lmdb, sort to show new on top 2026-05-01 11:42:35 +03:00
ardocrat 13bf8e830c node: reset data from settings 2026-05-01 02:18:47 +03:00
ardocrat 57f319edfc android: include application mime type 2026-04-30 20:36:42 +03:00
ardocrat 748aebffb6 ci: release runner for version and forgejo release 2026-04-30 20:16:12 +03:00
ardocrat b32085a423 node + wallet: update lmdb 2026-04-30 18:27:27 +03:00
ardocrat a9c65546e3 node: update default dns seeds, setup seeds for testnet on launch 2026-04-30 14:14:51 +03:00
ardocrat b94241b82a wallet: select external connection by default on creation if integrated node is not running 2026-04-30 13:53:44 +03:00
ardocrat 8a1a69b739 node: update seeds 2026-04-24 01:14:16 +03:00
ardocrat 01d17e25ee tor: update webtunnel list 2026-04-24 00:12:22 +03:00
ardocrat cab38097fa build: v0.3.5 2026-04-21 13:13:28 +03:00
32 changed files with 495 additions and 311 deletions
+4 -2
View File
@@ -13,8 +13,10 @@ jobs:
runs-on: ubuntu
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules
git submodule update --init
- name: Check commit
id: check
run: |
+112 -92
View File
@@ -10,7 +10,7 @@ on:
jobs:
version:
runs-on: ubuntu
runs-on: debian-release
outputs:
v: ${{ steps.version.outputs.v }}
pre: ${{ steps.version.outputs.pre }}
@@ -18,8 +18,10 @@ jobs:
last_tag: ${{ steps.check_prev.outputs.last_tag }}
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules
git submodule update --init
- name: Get version
id: version
run: |
@@ -52,6 +54,18 @@ jobs:
if: ${{ forgejo.ref_type == 'tag' && steps.check.outputs.exists == 'true' }}
working-directory: release
run: for f in *; do mv "$f" "$(echo "$f" | sed s/-dev-/-/)"; done
- name: Delete dev release
if: ${{ forgejo.ref_type == 'tag' && steps.check.outputs.exists == 'true' }}
uses: actions/delete-release@v1
with:
release_name: "${{ forgejo.ref_name }}-dev"
- name: Check previous release
id: check_prev
run: |
git fetch --tags
[[ ${{ forgejo.ref_type }} == 'tag' ]] && skip=0 || skip=1
last_tag=$(git describe --abbrev=0 --tags $(git rev-list --tags --skip=${skip} --max-count=1)) || true
echo "last_tag=${last_tag}" >> "$FORGEJO_OUTPUT"
- uses: actions/forgejo-release@v2.11.3
if: ${{ forgejo.ref_type == 'tag' && steps.check.outputs.exists == 'true' }}
with:
@@ -62,26 +76,17 @@ jobs:
prerelease: false
release-dir: ./release
release-notes: "Full Changelog: [${{ steps.check_prev.outputs.last_tag }}...${{ steps.version.outputs.v }}](https://code.gri.mw/${{ forgejo.repository }}/compare/${{ steps.check_prev.outputs.last_tag }}...${{ steps.version.outputs.v }})"
- name: Delete dev release
if: ${{ forgejo.ref_type == 'tag' && steps.check.outputs.exists == 'true' }}
uses: actions/delete-release@v1
with:
release_name: "${{ forgejo.ref_name }}-dev"
- name: Check previous release
id: check_prev
run: |
git fetch --tags
last_tag=$(git describe --abbrev=0 --tags $(git rev-list --tags --skip=1 --max-count=1))
echo "last_tag=${last_tag}" >> "$FORGEJO_OUTPUT"
android_libs:
android:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: ubuntu
runs-on: macos
needs: version
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
sed -i -- 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules
git submodule update --init
- name: Restore cargo cache
id: cache-cargo-restore
uses: actions/cache/restore@v5
@@ -93,11 +98,9 @@ jobs:
~/.cargo/git/db/
target/
key: grim-android-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Setup registry
run: |
echo -e '[registries.nexus]\nindex = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"\n[registry]\ndefault = "nexus"\n[source.crates-io]\nreplace-with = "nexus"\n[source.nexus]\nregistry = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"' > ~/.cargo/config.toml
- name: Build libs
run: |
rustup -q update
chmod +x scripts/android.sh && ./scripts/android.sh lib ${{ needs.version.outputs.v }}
- name: Save cargo cache
uses: actions/cache/save@v5
@@ -109,20 +112,6 @@ jobs:
~/.cargo/git/db/
target/
key: ${{ steps.cache-cargo-restore.outputs.cache-primary-key }}
- name: Upload artifacts
run: |
cd android/app/src/main
tar -czf jniLibs.tar.gz jniLibs
curl -v -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file jniLibs.tar.gz ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/jniLibs.tar.gz
android_release:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: ubuntu-android
needs: [version, android_libs]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Restore gradle cache
id: cache-gradle-restore
uses: actions/cache/restore@v5
@@ -133,23 +122,17 @@ jobs:
key: grim-android-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Download artifacts
run: |
cd android/app/src/main
curl -o jniLibs.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/jniLibs.tar.gz
tar -xzf jniLibs.tar.gz
rm jniLibs.tar.gz
- name: Setup build
run: |
chmod +x android/gradlew
echo "${{ secrets.ANDROID_KEYSTORE }}" > release.keystore.txt
base64 -d release.keystore.txt > android/keystore
base64 -d < release.keystore.txt -o android/keystore
echo "${{ secrets.ANDROID_KEYSTORE_PROPS }}" > release.keystore.props.txt
base64 -d release.keystore.props.txt > android/keystore.properties
base64 -d < release.keystore.props.txt -o android/keystore.properties
mkdir ~/.gradle && touch ~/.gradle/gradle.properties
printf "mavenHost=${{ secrets.MAVEN_HOST }}\n" >> ~/.gradle/gradle.properties
printf "mavenHost=${{ secrets.MAVEN_LOCAL_HOST }}\n" >> ~/.gradle/gradle.properties
printf "mavenUser=${{ secrets.MAVEN_USER }}\n" >> ~/.gradle/gradle.properties
printf "mavenPassword=${{ secrets.MAVEN_PASSWORD }}" >> ~/.gradle/gradle.properties
printf "mavenPassword=${{ secrets.MAVEN_PASSWORD }}" >> ~/.gradle/gradle.properties
- name: Release ARMv7+v8 APK
working-directory: android
run: |
@@ -194,16 +177,18 @@ jobs:
mkdir release
mv android/grim* release
tar -czf android.tar.gz release
curl -v -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file android.tar.gz ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/android.tar.gz
curl -s -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file android.tar.gz ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/android.tar.gz
linux_arm:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: ubuntu
needs: [version, android_libs]
runs-on: debian-rust-arm
needs: [version]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules
git submodule update --init
- name: Restore cargo cache
id: cache-cargo-restore
uses: actions/cache/restore@v5
@@ -217,9 +202,11 @@ jobs:
key: grim-linux-arm-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Setup registry
run: |
echo -e '[registries.nexus]\nindex = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"\n[registry]\ndefault = "nexus"\n[source.crates-io]\nreplace-with = "nexus"\n[source.nexus]\nregistry = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"' > ~/.cargo/config.toml
echo -e '[registries.nexus]\nindex = "sparse+${{ secrets.MAVEN_LOCAL_HOST }}/repository/cargo/"\n[registry]\ndefault = "nexus"\n[source.crates-io]\nreplace-with = "nexus"\n[source.nexus]\nregistry = "sparse+${{ secrets.MAVEN_LOCAL_HOST }}/repository/cargo/"' > ~/.cargo/config.toml
- name: Release Linux ARM
run: cargo zigbuild --release --target aarch64-unknown-linux-gnu
run: |
rustup -q update
cargo zigbuild --release --target aarch64-unknown-linux-gnu
- name: Save cargo cache
uses: actions/cache/save@v5
with:
@@ -230,28 +217,45 @@ jobs:
~/.cargo/git/db/
target/
key: ${{ steps.cache-cargo-restore.outputs.cache-primary-key }}
- name: AppImage ARM
- name: Upload artifacts
run: |
curl -s -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file target/aarch64-unknown-linux-gnu/release/grim ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/grim-linux-arm
linux_arm_appimage:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: debian-arm
needs: [version, linux_arm]
steps:
- uses: actions/checkout@v6
- name: Download Artifact
run: |
wget ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/grim-linux-arm
- name: AppImage
shell: bash
run: |
mkdir release
cp target/aarch64-unknown-linux-gnu/release/grim linux/Grim.AppDir/AppRun
appimagetool linux/Grim.AppDir grim-${{ needs.version.outputs.v }}-linux-arm.AppImage
cp grim-${{ needs.version.outputs.v }}-linux-arm.AppImage release/
chmod +x grim-linux-arm
mv grim-linux-arm linux/Grim.AppDir/AppRun
ARCH=aarch64 appimagetool linux/Grim.AppDir grim-${{ needs.version.outputs.v }}-linux-arm.AppImage
mv grim-${{ needs.version.outputs.v }}-linux-arm.AppImage release/
- name: Checksum AppImage ARM
working-directory: release
run: sha256sum grim-${{ needs.version.outputs.v }}-linux-arm.AppImage > grim-${{ needs.version.outputs.v }}-linux-arm-appimage-sha256sum.txt
- name: Upload artifacts
run: |
tar -czf linux-arm.tar.gz release
curl -v -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file linux-arm.tar.gz ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/linux-arm.tar.gz
tar -czf linux-arm.appimage.tar.gz release
curl -s -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file linux-arm.appimage.tar.gz ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/linux-arm.appimage.tar.gz
linux_x86:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: ubuntu-linux-x86
runs-on: debian-rust-x86_64
needs: [version]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules
git submodule update --init
- name: Restore cargo cache
id: cache-cargo-restore
uses: actions/cache/restore@v5
@@ -262,12 +266,14 @@ jobs:
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: grim-linux-x86-cargo-${{ hashFiles('**/Cargo.lock') }}
key: grim-linux-arm-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Setup registry
run: |
echo -e '[registries.nexus]\nindex = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"\n[registry]\ndefault = "nexus"\n[source.crates-io]\nreplace-with = "nexus"\n[source.nexus]\nregistry = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"' > ~/.cargo/config.toml
echo -e '[registries.nexus]\nindex = "sparse+${{ secrets.MAVEN_LOCAL_HOST }}/repository/cargo/"\n[registry]\ndefault = "nexus"\n[source.crates-io]\nreplace-with = "nexus"\n[source.nexus]\nregistry = "sparse+${{ secrets.MAVEN_LOCAL_HOST }}/repository/cargo/"' > ~/.cargo/config.toml
- name: Release Linux x86
run: cargo zigbuild --release --target x86_64-unknown-linux-gnu
run: |
rustup -q update
cargo zigbuild --release --target x86_64-unknown-linux-gnu
- name: Save cargo cache
uses: actions/cache/save@v5
with:
@@ -281,25 +287,27 @@ jobs:
- name: AppImage x86
run: |
mkdir release
cp target/x86_64-unknown-linux-gnu/release/grim linux/Grim.AppDir/AppRun
mv target/x86_64-unknown-linux-gnu/release/grim linux/Grim.AppDir/AppRun
appimagetool linux/Grim.AppDir grim-${{ needs.version.outputs.v }}-linux-x86_64.AppImage
cp grim-${{ needs.version.outputs.v }}-linux-x86_64.AppImage release/
mv grim-${{ needs.version.outputs.v }}-linux-x86_64.AppImage release/
- name: Checksum AppImage x86
working-directory: release
run: sha256sum grim-${{ needs.version.outputs.v }}-linux-x86_64.AppImage > grim-${{ needs.version.outputs.v }}-linux-x86_64-appimage-sha256sum.txt
- name: Upload artifacts
run: |
tar -czf linux-x86_64.tar.gz release
curl -v -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file linux-x86_64.tar.gz ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/linux-x86_64.tar.gz
tar -czf linux-x86_64.appimage.tar.gz release
curl -s -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file linux-x86_64.appimage.tar.gz ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/linux-x86_64.appimage.tar.gz
macos:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: ubuntu
needs: [version, android_libs, linux]
runs-on: macos
needs: [version, android]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
sed -i -- 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules
git submodule update --init
- run: mkdir release
- name: Restore cargo cache
id: cache-cargo-restore
@@ -312,13 +320,14 @@ jobs:
~/.cargo/git/db/
target/
key: grim-macos-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Setup registry
run: |
echo -e '[registries.nexus]\nindex = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"\n[registry]\ndefault = "nexus"\n[source.crates-io]\nreplace-with = "nexus"\n[source.nexus]\nregistry = "sparse+${{ secrets.MAVEN_HOST }}/repository/cargo/"' > ~/.cargo/config.toml
- name: Release MacOS Universal
run: |
cargo zigbuild --release --target universal2-apple-darwin
cp target/universal2-apple-darwin/release/grim macos/Grim.app/Contents/MacOS
rustup -q update
export MACOSX_DEPLOYMENT_TARGET=11.0
cargo build --release --target x86_64-apple-darwin
cargo build --release --target aarch64-apple-darwin
lipo -create -output grim "target/x86_64-apple-darwin/release/grim" "target/aarch64-apple-darwin/release/grim"
mv grim macos/Grim.app/Contents/MacOS
- name: Save cargo cache
uses: actions/cache/save@v5
with:
@@ -340,7 +349,7 @@ jobs:
- name: Upload artifacts
run: |
tar -czf macos.tar.gz release
curl -v -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file macos.tar.gz ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/macos.tar.gz
curl -s -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file macos.tar.gz ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/macos.tar.gz
windows:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
@@ -348,11 +357,22 @@ jobs:
needs: [version]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Checkout submodules
run: |
(Get-content .gitmodules) | Foreach-Object {$_ -replace "https://code.gri.mw", "${{ secrets.REPO_HOST }}"} | Set-Content .gitmodules
git submodule update --init
- name: Update UpgradeCode
shell: powershell
run: |
$guid = [guid]::NewGuid().ToString()
$wix = [xml](Get-Content wix/main.wxs)
$wix.Wix.Product.UpgradeCode = $guid
$wix.Save("wix/main.wxs")
Get-Content wix/main.wxs
- run: mkdir release
- name: Release Windows x86
run: |
rustup -q update
cargo wix -p grim -o grim-${{ needs.version.outputs.v }}-win-x86_64.msi --nocapture
mv grim-${{ needs.version.outputs.v }}-win-x86_64.msi release\
Compress-Archive -Path target\release\grim.exe -DestinationPath grim-${{ needs.version.outputs.v }}-win-x86_64.zip
@@ -366,28 +386,28 @@ jobs:
run: |
tar -czf windows.tar.gz release
Remove-Item alias:curl
curl -v -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file windows.tar.gz ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/windows.tar.gz
curl -s -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} --upload-file windows.tar.gz ${{ secrets.MAVEN_LOCAL_HOST }}/repository/grim-ci/${{ forgejo.repository }}/windows.tar.gz
release:
if: ${{ forgejo.ref_type == 'branch' || needs.version.outputs.exists == 'false' }}
runs-on: ubuntu
needs: [version, android_release, linux, linux_x86, macos, windows]
runs-on: debian-release
needs: [version, android, linux_x86, linux_arm_appimage, macos, windows]
steps:
- name: Download All Artifacts
run: |
curl -o android.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/android.tar.gz
curl -s -o android.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci/${{ forgejo.repository }}/android.tar.gz
tar -xzf android.tar.gz
rm android.tar.gz
curl -o linux-arm.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/linux-arm.tar.gz
tar -xzf linux-arm.tar.gz
rm linux-arm.tar.gz
curl -o linux-x86_64.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/linux-x86_64.tar.gz
tar -xzf linux-x86_64.tar.gz
rm linux-x86_64.tar.gz
curl -o macos.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/macos.tar.gz
curl -s -o linux-x86_64.appimage.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci/${{ forgejo.repository }}/linux-x86_64.appimage.tar.gz
tar -xzf linux-x86_64.appimage.tar.gz
rm linux-x86_64.appimage.tar.gz
curl -s -o linux-arm.appimage.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci/${{ forgejo.repository }}/linux-arm.appimage.tar.gz
tar -xzf linux-arm.appimage.tar.gz
rm linux-arm.appimage.tar.gz
curl -s -o macos.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci/${{ forgejo.repository }}/macos.tar.gz
tar -xzf macos.tar.gz
rm macos.tar.gz
curl -o windows.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci-artifacts/${{ forgejo.repository }}/windows.tar.gz
curl -s -o windows.tar.gz -u ${{ secrets.MAVEN_USER }}:${{ secrets.MAVEN_PASSWORD }} ${{ secrets.MAVEN_HOST }}/repository/grim-ci/${{ forgejo.repository }}/windows.tar.gz
tar -xzf windows.tar.gz
rm windows.tar.gz
- name: Upload release to Forgejo
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Copyright 2026 The Grim Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
rustfmt --version &>/dev/null
if [ $? != 0 ]; then
printf "[pre_commit] \033[0;31merror\033[0m: \"rustfmt\" not available. \n"
printf "[pre_commit] \033[0;31merror\033[0m: rustfmt can be installed via - \n"
printf "[pre_commit] $ rustup component add rustfmt-preview \n"
exit 1
fi
problem_files=()
# first collect all the files that need reformatting
for file in $(git diff --name-only --cached); do
if [ ${file: -3} == ".rs" ]; then
rustfmt --check $file &>/dev/null
if [ $? != 0 ]; then
problem_files+=($file)
fi
fi
done
if [ ${#problem_files[@]} == 0 ]; then
# nothing to do
printf "[pre_commit] rustfmt \033[0;32mok\033[0m \n"
else
# reformat the files that need it and re-stage them.
printf "[pre_commit] the following files were rustfmt'd before commit: \n"
for file in ${problem_files[@]}; do
rustfmt $file
git add $file
printf "\033[0;32m $file\033[0m \n"
done
fi
exit 0
Generated
+108 -31
View File
@@ -1159,12 +1159,6 @@ dependencies = [
"bitcoin-private",
]
[[package]]
name = "bitflags"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -1320,6 +1314,9 @@ name = "built"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64"
dependencies = [
"git2",
]
[[package]]
name = "bumpalo"
@@ -2518,6 +2515,15 @@ version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
[[package]]
name = "doxygen-rs"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9"
dependencies = [
"phf 0.11.3",
]
[[package]]
name = "dpi"
version = "0.1.2"
@@ -3579,12 +3585,6 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312d2295c7302019c395cfb90dacd00a82a2eabd700429bba9c7a3f38dbbe11b"
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]]
name = "generic-array"
version = "0.12.4"
@@ -3696,6 +3696,19 @@ version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
[[package]]
name = "git2"
version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b"
dependencies = [
"bitflags 2.10.0",
"libc",
"libgit2-sys",
"log",
"url",
]
[[package]]
name = "gl_generator"
version = "0.14.0"
@@ -3886,7 +3899,7 @@ dependencies = [
[[package]]
name = "grim"
version = "0.3.4"
version = "0.3.5"
dependencies = [
"android-activity",
"android_logger",
@@ -4098,6 +4111,7 @@ name = "grin_p2p"
version = "5.4.0"
dependencies = [
"bitflags 1.3.2",
"built",
"bytes 0.5.6",
"chrono",
"enum_primitive",
@@ -4164,7 +4178,6 @@ dependencies = [
"http 0.2.12",
"hyper 0.14.32",
"hyper-rustls 0.23.2",
"lmdb-zero",
"log",
"rand 0.6.5",
"rustls 0.20.9",
@@ -4184,8 +4197,8 @@ dependencies = [
"croaring",
"grin_core",
"grin_util",
"heed",
"libc",
"lmdb-zero",
"log",
"memmap",
"serde",
@@ -4549,6 +4562,44 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "heed"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad82d6598ccf1dac15c8b758a1bd282b755b6776be600429176757190a1b0202"
dependencies = [
"bitflags 2.10.0",
"byteorder",
"heed-traits",
"heed-types",
"libc",
"lmdb-master-sys",
"once_cell",
"page_size",
"serde",
"synchronoise",
"url",
]
[[package]]
name = "heed-traits"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff"
[[package]]
name = "heed-types"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c255bdf46e07fb840d120a36dcc81f385140d7191c76a7391672675c01a55d"
dependencies = [
"bincode 1.3.3",
"byteorder",
"heed-traits",
"serde",
"serde_json",
]
[[package]]
name = "hermit-abi"
version = "0.5.2"
@@ -5574,13 +5625,15 @@ dependencies = [
]
[[package]]
name = "liblmdb-sys"
version = "0.2.2"
name = "libgit2-sys"
version = "0.18.3+1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49"
checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487"
dependencies = [
"gcc",
"cc",
"libc",
"libz-sys",
"pkg-config",
]
[[package]]
@@ -5641,6 +5694,18 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libz-sys"
version = "1.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "linked-hash-map"
version = "0.5.6"
@@ -5672,15 +5737,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
[[package]]
name = "lmdb-zero"
version = "0.4.4"
name = "lmdb-master-sys"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13416eee745b087c22934f35f1f24da22da41ba2a5ce197143d168ce055cc58d"
checksum = "aaeb9bd22e73bd1babffff614994b341e9b2008de7bb73bf1f7e9154f1978f8b"
dependencies = [
"bitflags 0.9.1",
"cc",
"doxygen-rs",
"libc",
"liblmdb-sys",
"supercow",
]
[[package]]
@@ -7012,6 +7076,16 @@ dependencies = [
"sha2 0.10.9",
]
[[package]]
name = "page_size"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "parking"
version = "2.2.1"
@@ -9405,12 +9479,6 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "supercow"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63"
[[package]]
name = "svgtypes"
version = "0.15.3"
@@ -9460,6 +9528,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
[[package]]
name = "synchronoise"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2"
dependencies = [
"crossbeam-queue",
]
[[package]]
name = "synstructure"
version = "0.13.2"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "grim"
version = "0.3.4"
version = "0.3.5"
authors = ["Ardocrat <ardocrat@gri.mw>"]
description = "Cross-platform GUI for Grin with focus on usability and availability to be used by anyone, anywhere."
license = "Apache-2.0"
+1 -1
View File
@@ -12,7 +12,7 @@ android {
minSdk 24
targetSdk 36
versionCode 5
versionName "0.3.4"
versionName "0.3.5"
}
lint {
+1
View File
@@ -54,6 +54,7 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
<data android:mimeType="application/*" />
<data android:pathPattern=".*\\.slatepack" />
</intent-filter>
+2 -2
View File
@@ -300,8 +300,8 @@ network_settings:
ban_window_desc: Die Entscheidung über das Verbot trifft der Knoten auf der Grundlage der Korrektheit der von der Gegenstelle erhaltenen Daten.
max_inbound_count: 'Maximale Anzahl der eingehenden Peer-Verbindungen:'
max_outbound_count: 'Maximale Anzahl von ausgehenden Peer-Verbindungen:'
reset_peers_desc: Peer-Daten zurücksetzen. Verwenden Sie diese Funktion nur, wenn es Probleme beim finden von Peers gibt.
reset_peers: Peers zurücksetzten
reset_data_desc: Reset-Knotendaten. Verwenden Sie diese Funktion nur, wenn es Probleme mit der Synchronisation gibt.
reset_data: Daten zurücksetzten
modal:
cancel: Abbrechen
save: Speichern
+2 -2
View File
@@ -300,8 +300,8 @@ network_settings:
ban_window_desc: The decision to ban is made by node, based on the correctness of the data received from the peer.
max_inbound_count: 'Maximum number of inbound peer connections:'
max_outbound_count: 'Maximum number of outbound peer connections:'
reset_peers_desc: Reset peers data. Use it with a caution only if there are problems with finding peers.
reset_peers: Reset peers
reset_data_desc: Reset the node data. Use it with a caution only if there are problems with synchronization.
reset_data: Reset data
modal:
cancel: Cancel
save: Save
+2 -2
View File
@@ -300,8 +300,8 @@ network_settings:
ban_window_desc: La décision de bannir est prise par le noeud, en fonction de la validité des données reçues du pair.
max_inbound_count: 'Nombre maximum de connexions de pairs entrants :'
max_outbound_count: 'Nombre maximum de connexions de pairs sortants :'
reset_peers_desc: Réinitialiser les données des pairs. Utilisez-le avec précaution uniquement en cas de problèmes pour trouver des pairs.
reset_peers: Réinitialiser les pairs
reset_data_desc: Réinitialisez les données du noeud. Utilisez-le avec prudence uniquement en cas de problème de synchronisation.
reset_data: Réinitialisation des données
modal:
cancel: Annuler
save: Sauvegarder
+2 -2
View File
@@ -300,8 +300,8 @@ network_settings:
ban_window_desc: Решение о запрете принимается узлом, основываясь на корректности данных полученных от пира.
max_inbound_count: 'Максимальное количество входящих подключений пиров:'
max_outbound_count: 'Максимальное количество исходящих подключений к пирам:'
reset_peers_desc: Сбросить данные пиров. Используйте с осторожностью, только при наличии проблем с поиском пиров.
reset_peers: Сбросить пиры
reset_data_desc: Сбросить данные узла. Используйте с осторожностью, только при наличии проблем с синхронизацией.
reset_data: Сброс данных
modal:
cancel: Отмена
save: Сохранить
+2 -2
View File
@@ -300,8 +300,8 @@ network_settings:
ban_window_desc: Banlama karari, peerden alinan verilerin dogruluguna bagli olarak Node tarafindan verilir.
max_inbound_count: 'Maksimum gelen Peer baglanti sayisi:'
max_outbound_count: 'Maksimum giden Peer baglanti sayisi:'
reset_peers_desc: Peers verilerini sifirlayin. Yalnizca Peers bulma konusunda sorun yasiyorsaniz dikkatli kullanin.
reset_peers: Peers Resetle
reset_data_desc: Node verisini sifirlama. Sadece senkronizasyonda sorun varsa dikkatli kullanin.
reset_data: Verileri sifirlama
modal:
cancel: Iptal
save: Kaydet
+2 -2
View File
@@ -300,8 +300,8 @@ network_settings:
ban_window_desc: 禁止的决定是由节点 根据从网络对点收到的数据的正确性做出的.
max_inbound_count: '入站网络对点连接的最大数量:'
max_outbound_count: '最大出站网络对点连接数:'
reset_peers_desc: 重置网络对点数据。仅当查找网络对点出现问题时,才请谨慎使用.
reset_peers: 重置网络对点
reset_data_desc: 重置点数据。只有在出现同步问题时才需谨慎使用.
reset_data: 重置数据
modal:
cancel: 取消
save: 保存
+1 -1
View File
@@ -21,7 +21,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.3.4</string>
<string>0.3.5</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
+1 -1
Submodule node updated: 42b928a42f...3a37d24dca
+2
View File
@@ -0,0 +1,2 @@
hard_tabs = true
edition = "2024"
-3
View File
@@ -41,13 +41,10 @@ function build_lib() {
sed -i -e 's/"cdylib","rlib"]/"rlib"]/g' Cargo.toml
sed -i -e 's/"rlib"]/"cdylib","rlib"]/g' Cargo.toml
# Fix for https://stackoverflow.com/questions/57193895/error-use-of-undeclared-identifier-pthread-mutex-robust-cargo-build-liblmdb-s
export CPPFLAGS="-DMDB_USE_ROBUST=0" && export CFLAGS="-DMDB_USE_ROBUST=0"
cargo ndk -t "${arch}" -o android/app/src/main/jniLibs build --profile release-apk
if [ $? -ne 0 ]; then
success=0
fi
unset CPPFLAGS && unset CFLAGS
sed -i -e 's/"cdylib","rlib"]/"rlib"]/g' Cargo.toml
rm -f Cargo.toml-e
+56 -27
View File
@@ -16,7 +16,7 @@ use egui::{RichText, ScrollArea};
use egui::scroll_area::ScrollBarVisibility;
use crate::gui::Colors;
use crate::gui::icons::ARROW_COUNTER_CLOCKWISE;
use crate::gui::icons::{ARROW_COUNTER_CLOCKWISE, TRASH};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Content, View};
use crate::gui::views::network::setup::{DandelionSetup, NodeSetup, P2PSetup, PoolSetup, StratumSetup};
@@ -36,6 +36,9 @@ pub struct NetworkSettings {
pool: PoolSetup,
/// Dandelion server setup content.
dandelion: DandelionSetup,
/// Flag to check if reset of data was called.
data_reset: bool,
}
/// Identifier for settings reset confirmation [`Modal`].
@@ -49,6 +52,7 @@ impl Default for NetworkSettings {
stratum: StratumSetup::default(),
pool: PoolSetup::default(),
dandelion: DandelionSetup::default(),
data_reset: false,
}
}
}
@@ -110,6 +114,15 @@ impl ContentContainer for NetworkSettings {
// Draw Dandelion server setup section.
self.dandelion.ui(ui, cb);
// Draw content to reset the data.
if !Node::is_restarting() && !self.data_reset {
ui.add_space(4.0);
View::horizontal_line(ui, Colors::item_stroke());
ui.add_space(6.0);
self.reset_data_ui(ui);
}
ui.add_space(6.0);
View::horizontal_line(ui, Colors::stroke());
ui.add_space(6.0);
@@ -179,7 +192,7 @@ impl NetworkSettings {
}).collect::<Vec<_>>();
if saved_ip != selected_ip {
(on_change)(&selected_ip.to_string());
on_change(&selected_ip.to_string());
}
}
@@ -193,37 +206,53 @@ impl NetworkSettings {
ui.add_space(6.0);
});
}
/// Draw content to reset data.
fn reset_data_ui(&mut self, ui: &mut egui::Ui) {
ui.add_space(4.0);
View::colored_text_button(ui,
format!("{} {}", TRASH, t!("network_settings.reset_data")),
Colors::red(),
Colors::white_or_black(false), || {
Node::reset_data(false);
self.data_reset = true;
});
ui.add_space(6.0);
ui.label(RichText::new(t!("network_settings.reset_data_desc"))
.size(16.0)
.color(Colors::inactive_text())
);
ui.add_space(4.0);
}
}
/// Draw button to reset integrated node settings to default values.
fn reset_settings_ui(ui: &mut egui::Ui) {
ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.reset_settings_desc"))
.size(16.0)
.color(Colors::text(false)));
ui.add_space(8.0);
let button_text = format!("{} {}",
ARROW_COUNTER_CLOCKWISE,
t!("network_settings.reset_settings"));
View::action_button(ui, button_text, || {
// Show modal to confirm settings reset.
Modal::new(RESET_SETTINGS_CONFIRMATION_MODAL)
.position(ModalPosition::Center)
.title(t!("confirmation"))
.show();
});
// Show reminder to restart enabled node.
if Node::is_running() {
ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.restart_node_required"))
.size(16.0)
.color(Colors::gray())
);
}
ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.reset_settings_desc"))
.size(16.0)
.color(Colors::text(false)));
ui.add_space(8.0);
let button_text = format!("{} {}",
ARROW_COUNTER_CLOCKWISE,
t!("network_settings.reset_settings"));
View::action_button(ui, button_text, || {
// Show modal to confirm settings reset.
Modal::new(RESET_SETTINGS_CONFIRMATION_MODAL)
.position(ModalPosition::Center)
.title(t!("confirmation"))
.show();
});
// Show reminder to restart enabled node.
if Node::is_running() {
ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.restart_node_required"))
.size(16.0)
.color(Colors::gray())
);
}
ui.add_space(10.0);
}
/// Confirmation to reset settings to default values.
-30
View File
@@ -65,9 +65,6 @@ pub struct P2PSetup {
/// Maximum number of outbound peer connections.
max_outbound_count: String,
/// Flag to check if reset of peers was called.
peers_reset: bool,
}
/// Identifier for port value [`Modal`].
@@ -111,7 +108,6 @@ impl Default for P2PSetup {
ban_window_edit: NodeConfig::get_p2p_ban_window(),
max_inbound_count: NodeConfig::get_max_inbound_peers(),
max_outbound_count: NodeConfig::get_max_outbound_peers(),
peers_reset: false,
}
}
}
@@ -216,15 +212,6 @@ impl ContentContainer for P2PSetup {
// Show maximum outbound peers value setup.
self.max_outbound_ui(ui);
if !Node::is_restarting() && !self.peers_reset {
ui.add_space(6.0);
View::horizontal_line(ui, Colors::item_stroke());
ui.add_space(6.0);
// Show peers data reset content.
self.reset_peers_ui(ui);
}
});
}
}
@@ -753,23 +740,6 @@ impl P2PSetup {
ui.add_space(6.0);
});
}
/// Draw content to reset peers data.
fn reset_peers_ui(&mut self, ui: &mut egui::Ui) {
ui.add_space(4.0);
View::colored_text_button(ui,
format!("{} {}", TRASH, t!("network_settings.reset_peers")),
Colors::red(),
Colors::white_or_black(false), || {
Node::reset_peers(false);
self.peers_reset = true;
});
ui.add_space(6.0);
ui.label(RichText::new(t!("network_settings.reset_peers_desc"))
.size(16.0)
.color(Colors::inactive_text())
);
}
}
/// Draw peer list item.
@@ -64,7 +64,7 @@ impl WalletContentContainer for WalletAccountContent {
CREATE_MODAL_ID => self.create_account_content.ui(ui, wallet, modal, cb),
SEND_MODAL_ID => {
if let Some(c) = self.send_content.as_mut() {
c.modal_ui(ui, wallet, modal, cb);
c.ui(ui, wallet, modal, cb);
}
}
_ => {}
+30 -16
View File
@@ -58,36 +58,41 @@ pub struct WalletContent {
const INVOICE_MODAL_ID: &'static str = "invoice_request_modal";
/// Identifier for sending request creation [`Modal`].
const SEND_MODAL_ID: &'static str = "send_request_modal";
/// Identifier for Slatepack message input [`Modal`].
pub const MESSAGE_MODAL_ID: &'static str = "input_message_modal";
impl WalletContentContainer for WalletContent {
fn modal_ids(&self) -> Vec<&'static str> {
vec![
INVOICE_MODAL_ID,
SEND_MODAL_ID,
MESSAGE_MODAL_ID
MessageInputContent::MODAL_ID
]
}
fn modal_ui(&mut self, ui: &mut egui::Ui, w: &Wallet, m: &Modal, cb: &dyn PlatformCallbacks) {
match m.id {
INVOICE_MODAL_ID => {
if let Some(c) = self.invoice_content.as_mut() {
c.modal_ui(ui, w, m, cb);
if self.invoice_content.is_none() {
self.invoice_content = Some(InvoiceRequestContent::default());
}
self.invoice_content.as_mut().unwrap().ui(ui, w, m, cb);
}
SEND_MODAL_ID => {
if let Some(c) = self.send_content.as_mut() {
c.modal_ui(ui, w, m, cb);
if self.send_content.is_none() {
self.send_content = Some(SendRequestContent::new(None));
}
self.send_content.as_mut().unwrap().ui(ui, w, m, cb);
}
MESSAGE_MODAL_ID => {
if let Some(c) = self.message_content.as_mut() {
c.ui(ui, w, m, cb);
MessageInputContent::MODAL_ID => {
if self.message_content.is_none() {
self.message_content = Some(MessageInputContent::default());
}
self.message_content.as_mut().unwrap().ui(ui, w, m, cb);
}
_ => {
self.invoice_content = None;
self.send_content = None;
self.message_content = None;
}
_ => {}
}
}
@@ -394,7 +399,10 @@ impl WalletContent {
} else {
let (icon, color) = (FILE_ARROW_DOWN, Some(Colors::green()));
View::tab_button(ui, icon, color, active, |_| {
self.invoice_content = Some(InvoiceRequestContent::default());
if self.txs_content.is_none() {
self.txs_content = Some(WalletTransactionsContent::new(None));
self.settings_content = None;
}
Modal::new(INVOICE_MODAL_ID)
.position(ModalPosition::CenterTop)
.title(t!("wallets.receive"))
@@ -409,8 +417,11 @@ impl WalletContent {
} else {
let (icon, color) = (FILE_TEXT, Some(Colors::gold_dark()));
View::tab_button(ui, icon, color, active, |_| {
self.message_content = Some(MessageInputContent::default());
Modal::new(MESSAGE_MODAL_ID)
if self.txs_content.is_none() {
self.txs_content = Some(WalletTransactionsContent::new(None));
self.settings_content = None;
}
Modal::new(MessageInputContent::MODAL_ID)
.position(ModalPosition::Center)
.title(t!("wallets.messages"))
.show();
@@ -425,7 +436,10 @@ impl WalletContent {
} else {
let (icon, color) = (FILE_ARROW_UP, Some(Colors::red()));
View::tab_button(ui, icon, color, active, |_| {
self.send_content = Some(SendRequestContent::new(None));
if self.txs_content.is_none() {
self.txs_content = Some(WalletTransactionsContent::new(None));
self.settings_content = None;
}
Modal::new(SEND_MODAL_ID)
.position(ModalPosition::CenterTop)
.title(t!("wallets.send"))
@@ -488,7 +502,7 @@ impl WalletContent {
_ => {}
}
}
MESSAGE_MODAL_ID => {
MessageInputContent::MODAL_ID => {
match t {
WalletTask::VerifyProof(proof, res) => {
if let Some(res) = res {
+10 -9
View File
@@ -56,6 +56,9 @@ impl Default for MessageInputContent {
}
impl MessageInputContent {
/// Identifier for [`Modal`].
pub const MODAL_ID: &'static str = "input_message_modal";
/// Draw [`Modal`] content.
pub fn ui(&mut self,
ui: &mut egui::Ui,
@@ -236,15 +239,13 @@ impl MessageInputContent {
if self.message_edit.is_empty() {
return;
}
match wallet.parse_slatepack(&self.message_edit) {
Ok(_) => {
wallet.task(WalletTask::OpenMessage(self.message_edit.to_string()));
self.message_edit = "".to_string();
Modal::close();
}
Err(_) => {
self.parse_error = true;
}
if self.message_edit.starts_with("BEGINSLATEPACK.") &&
self.message_edit.ends_with("ENDSLATEPACK.") {
wallet.task(WalletTask::OpenMessage(self.message_edit.to_string()));
self.message_edit = "".to_string();
Modal::close();
} else {
self.parse_error = true;
}
}
}
@@ -37,7 +37,7 @@ impl Default for InvoiceRequestContent {
impl InvoiceRequestContent {
/// Draw [`Modal`] content.
pub fn modal_ui(&mut self,
pub fn ui(&mut self,
ui: &mut egui::Ui,
wallet: &Wallet,
modal: &Modal,
+5 -5
View File
@@ -73,11 +73,11 @@ impl SendRequestContent {
}
/// Draw [`Modal`] content.
pub fn modal_ui(&mut self,
ui: &mut egui::Ui,
wallet: &Wallet,
modal: &Modal,
cb: &dyn PlatformCallbacks) {
pub fn ui(&mut self,
ui: &mut egui::Ui,
wallet: &Wallet,
modal: &Modal,
cb: &dyn PlatformCallbacks) {
ui.add_space(6.0);
// Draw QR code scanner content if requested.
@@ -21,6 +21,7 @@ use crate::gui::views::network::ConnectionsContent;
use crate::gui::views::types::{ContentContainer, ModalPosition};
use crate::gui::views::{Modal, View};
use crate::gui::Colors;
use crate::node::Node;
use crate::wallet::types::ConnectionMethod;
use crate::wallet::{ConnectionsConfig, ExternalConnection};
@@ -35,8 +36,17 @@ pub struct ConnectionSettings {
impl Default for ConnectionSettings {
fn default() -> Self {
let method = {
let ext_conn_list = ConnectionsConfig::ext_conn_list();
if Node::is_running() || Node::is_starting() || ext_conn_list.is_empty() {
ConnectionMethod::Integrated
} else {
let ext_conn = ext_conn_list.get(0).unwrap();
ConnectionMethod::External(ext_conn.id, ext_conn.url.clone())
}
};
Self {
method: ConnectionMethod::Integrated,
method,
ext_conn_modal: ExternalConnectionModal::new(None),
}
}
+7 -7
View File
@@ -45,6 +45,13 @@ pub struct WalletTransactionsContent {
manual_sync: Option<u128>
}
/// Identifier for transaction information [`Modal`].
const TX_INFO_MODAL: &'static str = "tx_info_modal";
/// Identifier for transaction cancellation confirmation [`Modal`].
const CANCEL_TX_CONFIRMATION_MODAL: &'static str = "cancel_tx_conf_modal";
/// Identifier for transaction deletion confirmation [`Modal`].
const DELETE_TX_CONFIRMATION_MODAL: &'static str = "delete_tx_conf_modal";
impl WalletContentContainer for WalletTransactionsContent {
fn modal_ids(&self) -> Vec<&'static str> {
vec![TX_INFO_MODAL, CANCEL_TX_CONFIRMATION_MODAL, DELETE_TX_CONFIRMATION_MODAL]
@@ -78,13 +85,6 @@ impl WalletContentContainer for WalletTransactionsContent {
}
}
/// Identifier for transaction information [`Modal`].
const TX_INFO_MODAL: &'static str = "tx_info_modal";
/// Identifier for transaction cancellation confirmation [`Modal`].
const CANCEL_TX_CONFIRMATION_MODAL: &'static str = "cancel_tx_conf_modal";
/// Identifier for transaction deletion confirmation [`Modal`].
const DELETE_TX_CONFIRMATION_MODAL: &'static str = "delete_tx_conf_modal";
impl WalletTransactionsContent {
/// Height of transaction list item.
pub const TX_ITEM_HEIGHT: f32 = 75.0;
+23 -2
View File
@@ -28,6 +28,8 @@ use crate::gui::Colors;
use crate::wallet::types::{WalletTask, WalletTx};
use crate::wallet::Wallet;
use crate::AppConfig;
use crate::gui::views::types::ModalPosition;
use crate::gui::views::wallets::wallet::message::MessageInputContent;
/// Transaction information [`Modal`] content.
pub struct WalletTransactionContent {
@@ -219,6 +221,8 @@ impl WalletTransactionContent {
// Setup spacing between buttons.
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
let mut finalization_needed = false;
ui.columns(2, |columns| {
columns[0].vertical_centered_justified(|ui| {
// Draw button to show Slatepack message as QR code.
@@ -232,7 +236,12 @@ impl WalletTransactionContent {
let copy_text = format!("{} {}", COPY, t!("copy"));
View::button(ui, copy_text, Colors::white_or_black(false), || {
cb.copy_string_to_buffer(m.clone());
Modal::close();
// Show message input or close modal.
if tx.can_finalize() {
finalization_needed = true;
} else {
Modal::close();
}
});
});
});
@@ -249,10 +258,22 @@ impl WalletTransactionContent {
let name = format!("{}.{}.slatepack", slate_id, tx.state);
let data = m.as_bytes().to_vec();
cb.share_data(name, data).unwrap_or_default();
Modal::close();
// Show message input or close modal.
if tx.can_finalize() {
finalization_needed = true;
} else {
Modal::close();
}
}
});
});
if finalization_needed {
Modal::new(MessageInputContent::MODAL_ID)
.position(ModalPosition::Center)
.title(t!("wallets.messages"))
.show();
}
}
}
+48 -53
View File
@@ -28,7 +28,7 @@ use grin_p2p::msg::PeerAddrs;
use grin_p2p::Seeding;
use grin_servers::{Server, ServerStats, StratumServerConfig, StratumStats};
use grin_servers::common::types::Error;
use log::error;
use crate::node::{NodeConfig, NodeError, PeersConfig};
use crate::node::stratum::{StratumStopState, StratumServer};
@@ -57,8 +57,8 @@ pub struct Node {
stop_needed: AtomicBool,
/// Flag to check if app exit is needed after [`Server`] stop.
exit_after_stop: AtomicBool,
/// Flag to reset peers data and restart the [`Server`].
reset_peers: AtomicBool,
/// Flag to reset data and restart the [`Server`].
reset_data: AtomicBool,
/// Flag to change data directory and restart the [`Server`].
change_data_dir: AtomicBool,
@@ -78,7 +78,7 @@ impl Default for Node {
exit_after_stop: AtomicBool::new(false),
start_stratum_needed: AtomicBool::new(false),
error: Arc::new(RwLock::new(None)),
reset_peers: AtomicBool::new(false),
reset_data: AtomicBool::new(false),
change_data_dir: AtomicBool::new(false),
}
}
@@ -89,26 +89,20 @@ impl Node {
pub const STATS_UPDATE_DELAY: Duration = Duration::from_millis(1000);
/// Default Mainnet DNS Seeds
pub const MAINNET_DNS_SEEDS: &'static[&'static str] = &[
"main.gri.mw",
"grincoin.org",
"mainnet.grinffindor.org",
"mainnet.seed.grin.lesceller.com",
"grinseed.revcore.net",
"mainnet-seed.grinnode.live",
"mainnet.grin.punksec.de",
"grinnode.30-r.com"
pub const MAINNET_DNS_SEEDS: &[&str] = &[
"mainnet-seed.grinnode.live", // info@grinnode.live
"grincoin.org", // xmpp:aglkm@conversations.im
"main.gri.mw", // admin@gri.mw
"mainnet.grinffindor.org", // support@grinffindor.org
"main-seed.grin.money", // support@grinily.com
];
/// Default Testnet DNS Seeds
pub const TESTNET_DNS_SEEDS: &'static[&'static str] = &[
"test.gri.mw",
"testnet.grincoin.org",
"testnet.grinffindor.org",
"floonet.seed.grin.lesceller.com",
"grintestseed.revcore.net",
"testnet.grin.punksec.de",
"testnet.grinnode.30-r.com"
pub const TESTNET_DNS_SEEDS: &[&str] = &[
"testnet.grincoin.org", // xmpp:aglkm@conversations.im
"test.gri.mw", // admin@gri.mw
"testnet.grinffindor.org", // support@grinffindor.org
"test-seed.grin.money", // support@grinily.com
];
/// Stop the [`Server`] and setup exit flag after if needed.
@@ -175,12 +169,12 @@ impl Node {
/// Check if [`Node`] is restarting.
pub fn is_restarting() -> bool {
NODE_STATE.restart_needed.load(Ordering::Relaxed) || Self::reset_peers_needed()
NODE_STATE.restart_needed.load(Ordering::Relaxed) || Self::reset_data_needed()
}
/// Check if reset of [`Server`] peers is needed.
fn reset_peers_needed() -> bool {
NODE_STATE.reset_peers.load(Ordering::Relaxed)
fn reset_data_needed() -> bool {
NODE_STATE.reset_data.load(Ordering::Relaxed)
}
/// Get node [`Server`] statistics.
@@ -269,9 +263,9 @@ impl Node {
server.stop();
// Wait server after stop.
thread::sleep(Duration::from_millis(5000));
// Reset peers data if requested.
if Self::reset_peers_needed() {
Node::reset_peers(true);
// Reset data if requested.
if Self::reset_data_needed() {
Node::reset_data(true);
}
// Reset stratum stats.
{
@@ -285,7 +279,7 @@ impl Node {
NODE_STATE.restart_needed.store(false, Ordering::Relaxed);
}
Err(e) => {
// Set an error.
error!("Error starting node: {:?}", e);
{
let mut w_err = NODE_STATE.error.write();
*w_err = Some(e);
@@ -339,7 +333,7 @@ impl Node {
}
}
Err(e) => {
// Set an error.
error!("Error starting node: {:?}", e);
{
let mut w_err = NODE_STATE.error.write();
*w_err = Some(e);
@@ -434,24 +428,20 @@ impl Node {
}
}
/// Reset [`Server`] peers data.
pub fn reset_peers(force: bool) {
/// Reset [`Server`] data.
pub fn reset_data(force: bool) {
if force || !Node::is_running() {
// Get saved server config.
let config = NodeConfig::node_server_config();
let server_config = config.server.clone();
// Remove peers folder.
let mut peers_dir = PathBuf::from(&server_config.db_root);
peers_dir.push("peer");
if peers_dir.exists() {
match fs::remove_dir_all(peers_dir) {
Ok(_) => {}
Err(_) => {}
}
// Remove data folder.
let data_dir = PathBuf::from(&server_config.db_root);
match fs::remove_dir_all(data_dir) {
Ok(_) => {}
Err(_) => {}
}
NODE_STATE.reset_peers.store(false, Ordering::Relaxed);
NODE_STATE.reset_data.store(false, Ordering::Relaxed);
} else {
NODE_STATE.reset_peers.store(true, Ordering::Relaxed);
NODE_STATE.reset_data.store(true, Ordering::Relaxed);
}
}
@@ -585,20 +575,25 @@ fn start_node_server() -> Result<Server, Error> {
PeersConfig::load_to_server_config(&mut config);
let mut server_config = config.server.clone();
// Setup Mainnet DNSSeed
if server_config.chain_type == ChainTypes::Mainnet && NodeConfig::is_default_seeding_type() {
// DNS seed setup.
if NodeConfig::is_default_seeding_type() {
server_config.p2p_config.seeding_type = Seeding::List;
server_config.p2p_config.seeds = Some(PeerAddrs::default());
for seed in Node::MAINNET_DNS_SEEDS {
let addr = format!("{}:3414", seed);
let is_mainnet = server_config.chain_type == ChainTypes::Mainnet;
let seed_list = if is_mainnet {
Node::MAINNET_DNS_SEEDS
} else {
Node::TESTNET_DNS_SEEDS
};
let seed_port = if is_mainnet {
3414
} else {
13414
};
for seed_addr in seed_list {
let addr = format!("{}:{}", seed_addr, seed_port);
if let Some(p) = PeersConfig::peer_to_addr(addr) {
let mut seeds = server_config
.p2p_config
.seeds
.clone()
.unwrap_or(PeerAddrs::default());
seeds.peers.insert(seeds.peers.len(), p);
server_config.p2p_config.seeds = Some(seeds);
server_config.p2p_config.seeds.as_mut().unwrap().peers.push(p)
}
}
}
+6 -6
View File
@@ -59,12 +59,12 @@ impl TorBridge {
/// Default webtunnel protocol connection line.
pub const DEFAULT_WEBTUNNEL_CONN_LINE: &'static str = "webtunnel [2001:db8:beb:5884:ffcc:bfe3:2858:b06b]:443 1E242C749707B4A68A269F0D31311CE36CDFEC28 url=https://wt.gri.mw/74Fm0lKUWWMMjZpKf6iSC0UH";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_1: &'static str = "webtunnel [2001:db8:1640:379c:ad30:db5f:bff5:37d0]:443 AF8F7548C886D6F53A652411DBB71D089517085A url=https://app05.oneclickhost.eu/alpfZGTB9FckCgOkOOA0OHlh";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_2: &'static str = "webtunnel [2001:db8:eedb:cae7:a345:4f72:f9cc:5de0]:443 B3C81E7A0CA474270DAA4A2C8633E1CA8935C37D url=https://wordpress.far-east-investment.ru/sORes7268CEUSRD7hAWvJU5A";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_3: &'static str = "webtunnel [2001:db8:945c:e0b9:7e4c:c974:ff00:d4c5]:443 91937F3EFB3BE5169788AC7C8BF07460B7E306DB url=https://kabel.entreri.de/YXbp1dNrJeOF8giAFFYWxvmf";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_4: &'static str = "webtunnel [2001:db8:4767:7aa2:df21:1b2b:d7f9:caee]:443 CD193CF0D0C29551928C01FCB28D1200D9F27CFA url=https://occurrence.pics/68SzSlQCRgnfSo32eLyjC1V3";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_5: &'static str = "webtunnel [2001:db8:ce90:3593:272e:4975:a031:55b]:443 12382A2F3912AD1983A97C8709CBAE47ADB60BE3 url=https://miranda.today/LWwxIXDHCyyScn7oDauPMTmX";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_6: &'static str = "webtunnel [2001:db8:a12b:ff8:8a1a:a05b:5f21:2ccc]:443 F2A9C5AEE0A420EB9D55F9497B3C0FA243A2A770 url=https://bridge.lovecloud.me/wss-wc3p0euqrlne98t9";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_1: &'static str = "webtunnel [2001:db8:289b:84cd:4be3:77f1:1cdd:9cb1]:443 D71C8E9C2180D2F35DEBF4A39BFCA6972F076D1C sni-imitation=yandex.ru,google.com,dzen.ru,vk.com,mail.ru,ozon.ru,ya.ru,www.wildberries.ru,rutube.ru,www.avito.ru,ok.ru,vkvideo.ru url=https://streaming.the-forgotten-tales.com/gz9X1VBgl0r1Xfx3dHdNl5Tl";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_2: &'static str = "webtunnel [2001:db8:dee9:5852:b4dc:7e14:21bd:c99b]:443 8ADF1761FA735FDD763781BB94A16EAB64A1CF6C url=https://app01.oneclickhost.eu/WJSgXJRlNnMStkuLZygVJ7lo";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_3: &'static str = "webtunnel [2001:db8:eedb:cae7:a345:4f72:f9cc:5de0]:443 B3C81E7A0CA474270DAA4A2C8633E1CA8935C37D url=https://wordpress.far-east-investment.ru/sORes7268CEUSRD7hAWvJU5A";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_4: &'static str = "webtunnel [2001:db8:945c:e0b9:7e4c:c974:ff00:d4c5]:443 91937F3EFB3BE5169788AC7C8BF07460B7E306DB url=https://kabel.entreri.de/YXbp1dNrJeOF8giAFFYWxvmf";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_5: &'static str = "webtunnel [2001:db8:7d4:9e13:8c7a:7e3:1f62:d790]:443 B7E362F9079D0C908F204581EB019034023BB224 url=https://balades-et-gouts.fr/xt70R9oyJt3B1xj89UCWPdLt";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_6: &'static str = "webtunnel [2001:db8:8c88:1b17:d7ae:cb68:f28e:e31c]:443 C115DAC2FE991CA25DDD43D7D4D398FEA9AA4C01 url=https://foglab.net/t9crLwo4LzFDWHdwcGf9gFrk";
pub const ADDITIONAL_WEBTUNNEL_CONN_LINE_7: &'static str = "webtunnel [2001:db8:8ed6:e6c9:5fc9:9f20:a373:2374]:443 1636A2EFFBAA4B162F5FF461A1663EB55C41AE11 url=https://hanoi.delivery/roQFPLtlspWT6yIKeXD6lEci";
pub const DEFAULT_WEBTUNNEL_CONN_LINES: [&'static str; 8] = [
+1 -6
View File
@@ -671,12 +671,7 @@ impl Wallet {
}
})
// Sort txs by creation date and confirmation status.
.sorted_by_key(|tx| if !tx.confirmed && (tx.tx_type == TxLogEntryType::TxSent ||
tx.tx_type == TxLogEntryType::TxReceived) {
-i64::MAX
} else {
-tx.creation_ts.timestamp()
})
.sorted_by_key(|tx| -tx.creation_ts.timestamp())
// Sort to show unconfirmed at top.
.sorted_by_key(|tx| {
tx.confirmed || tx.tx_type == TxLogEntryType::TxReceivedCancelled ||
+1 -1
Submodule wallet updated: 4f3d9aac25...c1d7070291
+2 -2
View File
@@ -7,8 +7,8 @@
<?endif ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Version="0.3.4" UpgradeCode="C19F9B41-CD13-4F0E-B27D-E0EF8CF1CE91" Language="1033" Name="Grim" Manufacturer="Ardocrat">
<Package Id="ECF79CAD-4441-45A7-B80C-7CC5773FAD82" InstallerVersion="300" Compressed="yes"/>
<Product Id="*" Version="0.3.5" UpgradeCode="C19F9B41-CD13-4F0E-B27D-E0EF8CF1CE91" Language="1033" Name="Grim" Manufacturer="Ardocrat">
<Package Id="E15A3211-C334-4B2D-8774-4834657A00B6" InstallerVersion="300" Compressed="yes"/>
<Media Id="1" Cabinet="grim.cab" EmbedCab="yes" />
<MajorUpgrade AllowDowngrades = "yes"/>