diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml
deleted file mode 100644
index cb2afa396..000000000
--- a/.github/workflows/cache_dependencies.yml
+++ /dev/null
@@ -1,84 +0,0 @@
-name: Cache Dependencies
-
-on:
-  workflow_dispatch:
-  push:
-    branches: [ main ]
-
-jobs:
-  test:
-
-    runs-on: ubuntu-20.04
-
-    steps:
-      - name: Free Disk Space (Ubuntu)
-        uses: insightsengineering/disk-space-reclaimer@v1
-        with:
-          tools-cache: true
-          android: false
-          dotnet: true
-          haskell: true
-          large-packages: true
-          swap-storage: true
-          docker-images: true
-
-      - uses: actions/checkout@v2
-      - uses: actions/setup-java@v2
-        with:
-          distribution: "temurin"
-          java-version: "17"
-      - name: Configure placeholder git details
-        run: |
-          git config --global user.email "CI@cakewallet.com"
-          git config --global user.name "Cake Github Actions"
-      - name: Flutter action
-        uses: subosito/flutter-action@v1
-        with:
-          flutter-version: "3.24.4"
-          channel: stable
-
-      - name: Install package dependencies
-        run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang
-
-      - name: Execute Build and Setup Commands
-        run: |
-          sudo mkdir -p /opt/android
-          sudo chown $USER /opt/android
-          cd /opt/android
-          -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-          cargo install cargo-ndk
-          git clone https://github.com/cake-tech/cake_wallet.git --branch main
-          cd cake_wallet/scripts/android/
-          ./install_ndk.sh
-          source ./app_env.sh cakewallet
-          chmod +x pubspec_gen.sh
-          ./app_config.sh
-
-      - name: Cache Externals
-        id: cache-externals
-        uses: actions/cache@v3
-        with:
-          path: |
-            /opt/android/cake_wallet/cw_haven/android/.cxx
-            /opt/android/cake_wallet/scripts/monero_c/release
-          key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
-
-      - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
-        name: Generate Externals
-        run: |
-          cd /opt/android/cake_wallet/scripts/android/
-          source ./app_env.sh cakewallet
-          ./build_monero_all.sh
-
-      - name: Cache Keystore
-        id: cache-keystore
-        uses: actions/cache@v3
-        with:
-          path: /opt/android/cake_wallet/android/app
-          key: keystore
-
-      - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
-        name: Generate KeyStore
-        run: |
-          cd /opt/android/cake_wallet/android/app
-          keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS
diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index cdd0e40b4..c5f875128 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -1,169 +1,93 @@
-name: PR Test Build
+name: Cake Wallet Android
 
-on:
-  pull_request:
-    branches: [main]
-  workflow_dispatch:
-    inputs:
-      branch:
-        description: "Branch name to build"
-        required: true
-        default: "main"
+on: [push]
 
+defaults:
+  run:
+    shell: bash
 jobs:
   PR_test_build:
-    runs-on: ubuntu-20.04
+    runs-on: linux-amd64
+    container:
+      image: ghcr.io/cake-tech/cake_wallet:main-linux
+      env:
+        STORE_PASS: test@cake_wallet
+        KEY_PASS: test@cake_wallet
+        MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
+        BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
+        ANDROID_AVD_HOME: /root/.android/avd
+      volumes:
+        - /opt/cw_cache_android/root/.cache:/root/.cache
+        - /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
+        - /opt/cw_cache_android/root/.ccache:/root/.ccache
+        - /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
+        - /opt/cw_cache_android/root/.gradle/:/root/.gradle
+        - /opt/cw_cache_android/root/.android/:/root/.android
+        - /opt/cw_cache_android/root/go/pkg:/root/go/pkg
+        - /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
+        - /dev/kvm:/dev/kvm
     strategy:
       matrix:
         api-level: [29]
-    env:
-      STORE_PASS: test@cake_wallet
-      KEY_PASS: test@cake_wallet
-      PR_NUMBER: ${{ github.event.number }}
 
     steps:
-      - name: is pr
-        if: github.event_name == 'pull_request'
-        run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV
-
-      - name: is not pr
-        if: github.event_name != 'pull_request'
-        run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENV
-
-      - name: Free Disk Space (Ubuntu)
-        uses: insightsengineering/disk-space-reclaimer@v1
-        with:
-          tools-cache: true
-          android: false
-          dotnet: true
-          haskell: true
-          large-packages: true
-          swap-storage: true
-          docker-images: true
-
-      - uses: actions/checkout@v2
-      - uses: actions/setup-java@v2
-        with:
-          distribution: "temurin"
-          java-version: "17"
-      - name: Configure placeholder git details
+      - name: Fix github actions messing up $HOME...
+        run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV'
+      - uses: actions/checkout@v4
+      - name: configure git
         run: |
-          git config --global user.email "CI@cakewallet.com"
-          git config --global user.name "Cake Github Actions"
-      - name: Flutter action
-        uses: subosito/flutter-action@v1
-        with:
-          flutter-version: "3.24.0"
-          channel: stable
-
-      - name: Install package dependencies
-        run: |
-          sudo apt update
-          sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang
-
-
-      - name: Clone Repo
-        run: |
-          sudo mkdir -p /opt/android
-          sudo chown $USER /opt/android
-          cd /opt/android
-          git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }}
-
-#      - name: Cache Keystore
-#        id: cache-keystore
-#        uses: actions/cache@v3
-#        with:
-#          path: /opt/android/cake_wallet/android/app
-#          key: keystore
-#
-#      - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
-      - name: Generate KeyStore
-        run: |
-          cd /opt/android/cake_wallet/android/app
-          keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS
-
-      - name: Execute Build and Setup Commands
-        run: |
-          cd /opt/android
-          -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-          cargo install cargo-ndk
-          cd cake_wallet/scripts/android/
-          ./install_ndk.sh
-          source ./app_env.sh cakewallet
-          chmod +x pubspec_gen.sh
-          ./app_config.sh
-
-      - name: Cache Externals
-        id: cache-externals
-        uses: actions/cache@v3
-        with:
-          path: |
-            /opt/android/cake_wallet/cw_haven/android/.cxx
-            /opt/android/cake_wallet/scripts/monero_c/release
-          key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
-
-      - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
-        name: Generate Externals
-        run: |
-          cd /opt/android/cake_wallet/scripts/android/
-          source ./app_env.sh cakewallet
-          ./build_monero_all.sh
-
-      - name: Install Flutter dependencies
-        run: |
-          cd /opt/android/cake_wallet
-          flutter pub get
-
-
-      - name: Install go and gomobile
-        run: |
-          # install go > 1.23:
-          wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
-          sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
-          export PATH=$PATH:/usr/local/go/bin
-          export PATH=$PATH:~/go/bin
-          go install golang.org/x/mobile/cmd/gomobile@latest
-          gomobile init
-
-      - name: Build mwebd
-        run: |
-          # paths are reset after each step, so we need to set them again:
-          export PATH=$PATH:/usr/local/go/bin
-          export PATH=$PATH:~/go/bin
-          cd /opt/android/cake_wallet/scripts/android/
-          ./build_mwebd.sh --dont-install
-
-      - name: Generate key properties
-        run: |
-          cd /opt/android/cake_wallet
-          dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS
-
-      - name: Generate localization
-        run: |
-          cd /opt/android/cake_wallet
-          dart run tool/generate_localization.dart
-
-      - name: Build generated code
-        run: |
-          cd /opt/android/cake_wallet
-          ./model_generator.sh
-
+          git config --global user.email "ci@cakewallet.com"
+          git config --global user.name "CakeWallet CI"
       - name: Add secrets
         run: |
-          cd /opt/android/cake_wallet
           touch lib/.secrets.g.dart
           touch cw_evm/lib/.secrets.g.dart
           touch cw_solana/lib/.secrets.g.dart
           touch cw_core/lib/.secrets.g.dart
           touch cw_nano/lib/.secrets.g.dart
           touch cw_tron/lib/.secrets.g.dart
-          echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
-          echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
-          echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
-          echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
-          echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
-          echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
-          echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
+          if [[ "x${{ secrets.SALT }}" == "x" ]];
+          then
+            echo "const salt = '954f787f12622067f7e548d9450c3832';" > lib/.secrets.g.dart
+          else
+            echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.KEY_CHAIN_SALT }}" == "x" ]];
+          then
+            echo "const keychainSalt = '2d2beba777dbf7dff7013b7a';" >> lib/.secrets.g.dart
+          else
+            echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.KEY }}" == "x" ]];
+          then
+            echo "const key = '638e98820ec10a2945e968435c9397a3';" >> lib/.secrets.g.dart
+          else
+            echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.WALLET_SALT }}" == "x" ]];
+          then
+            echo "const walletSalt = '8f7f1b70';" >> lib/.secrets.g.dart
+          else
+            echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.SHORT_KEY }}" == "x" ]];
+          then
+            echo "const shortKey = '653f270c2c152bc7ec864afe';" >> lib/.secrets.g.dart
+          else
+            echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.BACKUP_SALT }}" == "x" ]];
+          then
+            echo "const backupSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
+          else
+            echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.BACKUP_KEY_CHAIN_SALT }}" == "x" ]];
+          then
+            echo "const backupKeychainSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
+          else
+            echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
+          fi
           echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
           echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
@@ -213,86 +137,153 @@ jobs:
           echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
           echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart
+          # for tests
+          echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const litecoinTestWalletSeeds =  '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinCashTestWalletSeeds =  '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const nanoTestWalletSeeds =  '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinTestWalletReceiveAddress =  '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const ethereumTestWalletReceiveAddress =  '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const litecoinTestWalletReceiveAddress =  '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const polygonTestWalletReceiveAddress =  '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const solanaTestWalletReceiveAddress =  '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const tronTestWalletReceiveAddress =  '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const moneroTestWalletBlockHeight =  '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart
+      - name: prepare monero_c and cache
+        run: |
+          export MONEROC_HASH=$(cat scripts/prepare_moneroc.sh | grep 'git checkout' | xargs | awk '{ print $3 }')
+          echo MONEROC_HASH=$MONEROC_HASH >> /etc/environment
+          mkdir -p "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
+          pushd scripts
+            ln -s "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
+            ./prepare_moneroc.sh
+          popd
+          pushd scripts/monero_c
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" || true
+
+            rm -rf "$PWD/contrib/depends/built" "$PWD/monero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
+            rm -rf "$PWD/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
+            mkdir -p contrib/depends || true
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" "$PWD/contrib/depends/built"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" "$PWD/monero/contrib/depends/built"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" "$PWD/contrib/depends/sources"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" "$PWD/monero/contrib/depends/sources"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
+          popd
+
+      - name: Generate KeyStore
+        run: |
+          pushd /opt/generic_cache
+            if [[ ! -f key.jks ]];
+            then
+              keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS
+            else
+              echo "$PWD/key.jks exist, not generating"
+            fi
+          popd
+          cp /opt/generic_cache/key.jks android/app
+
+      - name: Execute Build and Setup Commands
+        run: |
+          pushd scripts/android
+            source ./app_env.sh cakewallet
+            ./app_config.sh
+          popd
+
+      - name: Build monero_c
+        run: |
+          pushd scripts/android/
+            source ./app_env.sh cakewallet
+            ./build_monero_all.sh
+          popd
+
+      - name: Install Flutter dependencies
+        run: |
+          flutter pub get
+
+      - name: Build mwebd
+        run: |
+          set -x -e
+          export MWEBD_HASH=$(cat scripts/android/build_mwebd.sh | grep 'git reset --hard' | xargs | awk '{ print $4 }')
+          echo MWEBD_HASH=$MWEBD_HASH >> /etc/environment
+          pushd scripts/android
+            gomobile init;
+            ./build_mwebd.sh --dont-install
+          popd
+
+      - name: Build generated code
+        run: |
+          ./model_generator.sh async
+
+      - name: Generate key properties
+        run: |
+          dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS
+
+      - name: Generate localization
+        run: |
+          dart run tool/generate_localization.dart
 
       - name: Rename app
         run: |
-          echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties
+          sanitized_branch_name=${BRANCH_NAME#origin/}  # Remove 'origin/' prefix if it exists
+          sanitized_branch_name=${sanitized_branch_name:0:16}  # Take only the first 16 characters
+          sanitized_branch_name=$(echo "$sanitized_branch_name" | tr '[:upper:]' '[:lower:]')  # Convert to lowercase
+          sanitized_branch_name=$(echo "$sanitized_branch_name" | sed 's/[^a-z0-9]//g')  # Remove all special characters
 
-      # Step 3: Download previous build number
-      - name: Download previous build number
-        id: download-build-number
-        run: |
-          # Download the artifact if it exists
-          if [[ ! -f build_number.txt ]]; then
-            echo "1" > build_number.txt
-          fi
-
-      # Step 4: Read and Increment Build Number
-      - name: Increment Build Number
-        id: increment-build-number
-        run: |
-          # Read current build number from file
-          BUILD_NUMBER=$(cat build_number.txt)
-          BUILD_NUMBER=$((BUILD_NUMBER + 1))
-          echo "New build number: $BUILD_NUMBER"
-
-          # Save the incremented build number
-          echo "$BUILD_NUMBER" > build_number.txt
-
-          # Export the build number to use in later steps
-          echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
-
-      # Step 5: Update pubspec.yaml with new build number
-      - name: Update build number
-        run: |
-          cd /opt/android/cake_wallet
-          sed -i "s/^version: .*/version: 1.0.$BUILD_NUMBER/" pubspec.yaml
+          echo -e "id=com.cakewallet.test_${sanitized_branch_name}\nname=${BRANCH_NAME}" > android/app.properties
 
       - name: Build
         run: |
-          cd /opt/android/cake_wallet
           flutter build apk --release --split-per-abi
 
-      #            - name: Push to App Center
-      #              run: |
-      #                echo 'Installing App Center CLI tools'
-      #                npm install -g appcenter-cli
-      #                echo "Publishing test to App Center"
-      #                appcenter distribute release \
-      #                    --group "Testers" \
-      #                    --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \
-      #                    --release-notes ${{ env.BRANCH_NAME }} \
-      #                    --app Cake-Labs/Cake-Wallet \
-      #                    --token ${{ secrets.APP_CENTER_TOKEN }} \
-      #                    --quiet
-
       - name: Rename apk file
         run: |
-          cd /opt/android/cake_wallet/build/app/outputs/flutter-apk
+          cd build/app/outputs/flutter-apk
           mkdir test-apk
-          cp app-arm64-v8a-release.apk test-apk/${{env.BRANCH_NAME}}.apk
-          cp app-x86_64-release.apk test-apk/${{env.BRANCH_NAME}}_x86.apk
+          cp app-arm64-v8a-release.apk test-apk/${BRANCH_NAME}.apk
+          cp app-x86_64-release.apk test-apk/${BRANCH_NAME}_x86.apk
+          cd test-apk
+          cp ${BRANCH_NAME}.apk ${BRANCH_NAME}_slack.apk
 
-      - name: Upload Artifact
-        uses: kittaakos/upload-artifact-as-is@v0
-        with:
-          path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/
-
-      # Re-upload updated build number for the next run
-      - name: Upload updated build number
-        uses: actions/upload-artifact@v3
-        with:
-          name: build_number
-          path: build_number.txt
-
-      - name: Send Test APK
+      - name: Find APK file
+        id: find_apk
+        run: |
+          set -x
+          apk_file=$(ls build/app/outputs/flutter-apk/test-apk/*_slack.apk || exit 1)
+          echo "APK_FILE=$apk_file" >> $GITHUB_ENV
+        
+      - name: Upload artifact to slack
+        if: ${{ !contains(github.event.head_commit.message, 'skip slack') }}
         continue-on-error: true
         uses: adrey/slack-file-upload-action@1.0.5
         with:
           token: ${{ secrets.SLACK_APP_TOKEN }}
-          path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk
+          path: ${{ env.APK_FILE }}
           channel: ${{ secrets.SLACK_APK_CHANNEL }}
-          title: "${{ env.BRANCH_NAME }}.apk"
-          filename: ${{ env.BRANCH_NAME }}.apk
           initial_comment: ${{ github.event.head_commit.message }}
 
+      - name: cleanup
+        run: rm -rf build/app/outputs/flutter-apk/test-apk/
+  
+      - name: Upload Artifact to github
+        uses: actions/upload-artifact@v4
+        with:
+          path: ${{ github.workspace }}/build/app/outputs/flutter-apk
+          name: "android apk"
\ No newline at end of file
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index 891327d1e..345c95c4f 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -1,139 +1,89 @@
-name: PR Test Build linux
+name: Cake Wallet Linux
 
-on:
-  pull_request:
-    branches: [main]
-  workflow_dispatch:
-    inputs:
-      branch:
-        description: "Branch name to build"
-        required: true
-        default: "main"
+on: [push]
 
+defaults:
+  run:
+    shell: bash
 jobs:
   PR_test_build:
-    runs-on: ubuntu-20.04
-    env:
-      STORE_PASS: test@cake_wallet
-      KEY_PASS: test@cake_wallet
-      PR_NUMBER: ${{ github.event.number }}
+    runs-on: linux-amd64
+    container:
+      image: ghcr.io/cake-tech/cake_wallet:main-linux
+      env:
+        STORE_PASS: test@cake_wallet
+        KEY_PASS: test@cake_wallet
+        MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
+        BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
+        DESKTOP_FORCE_MOBILE: Y
+      volumes:
+        - /opt/cw_cache_linux/root/.cache:/root/.cache
+        - /opt/cw_cache_linux/root/.ccache:/root/.ccache
+        - /opt/cw_cache_linux/root/.pub-cache/:/root/.pub-cache
+        - /opt/cw_cache_linux/root/go/pkg:/root/go/pkg
+        - /opt/cw_cache_linux/opt/generic_cache:/opt/generic_cache
+    strategy:
+      matrix:
+        api-level: [29]
 
     steps:
-      - name: is pr
-        if: github.event_name == 'pull_request'
-        run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV
-
-      - name: is not pr
-        if: github.event_name != 'pull_request'
-        run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENVg
-
-      - uses: actions/checkout@v2
-      - uses: actions/setup-java@v1
-        with:
-          java-version: "17.x"
-      - name: Configure placeholder git details
+      - name: Fix github actions messing up $HOME...
+        run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV'
+      - uses: actions/checkout@v4
+      - name: configure git
         run: |
-          git config --global user.email "CI@cakewallet.com"
-          git config --global user.name "Cake Github Actions"
-      - name: Flutter action
-        uses: subosito/flutter-action@v1
-        with:
-          flutter-version: "3.24.0"
-          channel: stable
-
-      - name: Install package dependencies
-        run: |
-          sudo apt update
-          sudo apt-get install -y curl unzip automake build-essential file pkg-config git python-is-python3 libtool libtinfo5 cmake clang
-
-      - name: Install desktop dependencies
-        run: |
-          sudo apt update
-          sudo apt install -y ninja-build libgtk-3-dev gperf
-      - name: Execute Build and Setup Commands
-        run: |
-          sudo mkdir -p /opt/android
-          sudo chown $USER /opt/android
-          cd /opt/android
-          -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-          cargo install cargo-ndk
-          git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }}
-          cd scripts && ./gen_android_manifest.sh && cd ..
-          cd cake_wallet/scripts/android/
-          source ./app_env.sh cakewallet
-          ./app_config.sh
-          cd ../../..
-          cd cake_wallet/scripts/linux/
-          source ./app_env.sh cakewallet
-          ./app_config.sh
-          cd ../../..
-
-      - name: Cache Externals
-        id: cache-externals
-        uses: actions/cache@v3
-        with:
-          path: |
-            /opt/android/cake_wallet/cw_haven/android/.cxx
-            /opt/android/cake_wallet/scripts/monero_c/release
-          key: linux_${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
-
-      - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
-        name: Generate Externals
-        run: |
-          cd /opt/android/cake_wallet/scripts/linux/
-          source ./app_env.sh cakewallet
-          ./build_monero_all.sh
-
-      - name: Install Flutter dependencies
-        run: |
-          cd /opt/android/cake_wallet
-          flutter pub get
-
-      - name: Install go and gomobile
-        run: |
-          # install go > 1.23:
-          wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
-          sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
-          export PATH=$PATH:/usr/local/go/bin
-          export PATH=$PATH:~/go/bin
-          go install golang.org/x/mobile/cmd/gomobile@latest
-          gomobile init
-
-      - name: Build mwebd
-        run: |
-          # paths are reset after each step, so we need to set them again:
-          export PATH=$PATH:/usr/local/go/bin
-          export PATH=$PATH:~/go/bin
-          # build mwebd:
-          cd /opt/android/cake_wallet/scripts/android/
-          ./build_mwebd.sh --dont-install
-
-      - name: Generate localization
-        run: |
-          cd /opt/android/cake_wallet
-          dart run tool/generate_localization.dart
-
-      - name: Build generated code
-        run: |
-          cd /opt/android/cake_wallet
-          ./model_generator.sh
-
+          git config --global user.email "ci@cakewallet.com"
+          git config --global user.name "CakeWallet CI"
       - name: Add secrets
         run: |
-          cd /opt/android/cake_wallet
           touch lib/.secrets.g.dart
           touch cw_evm/lib/.secrets.g.dart
           touch cw_solana/lib/.secrets.g.dart
           touch cw_core/lib/.secrets.g.dart
           touch cw_nano/lib/.secrets.g.dart
           touch cw_tron/lib/.secrets.g.dart
-          echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
-          echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
-          echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
-          echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
-          echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
-          echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
-          echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
+          if [[ "x${{ secrets.SALT }}" == "x" ]];
+          then
+            echo "const salt = '954f787f12622067f7e548d9450c3832';" > lib/.secrets.g.dart
+          else
+            echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.KEY_CHAIN_SALT }}" == "x" ]];
+          then
+            echo "const keychainSalt = '2d2beba777dbf7dff7013b7a';" >> lib/.secrets.g.dart
+          else
+            echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.KEY }}" == "x" ]];
+          then
+            echo "const key = '638e98820ec10a2945e968435c9397a3';" >> lib/.secrets.g.dart
+          else
+            echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.WALLET_SALT }}" == "x" ]];
+          then
+            echo "const walletSalt = '8f7f1b70';" >> lib/.secrets.g.dart
+          else
+            echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.SHORT_KEY }}" == "x" ]];
+          then
+            echo "const shortKey = '653f270c2c152bc7ec864afe';" >> lib/.secrets.g.dart
+          else
+            echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.BACKUP_SALT }}" == "x" ]];
+          then
+            echo "const backupSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
+          else
+            echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart
+          fi
+          if [[ "x${{ secrets.BACKUP_KEY_CHAIN_SALT }}" == "x" ]];
+          then
+            echo "const backupKeychainSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart
+          else
+            echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
+          fi
           echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
           echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
@@ -144,8 +94,6 @@ jobs:
           echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
           echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
-          echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
-          echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart
@@ -156,8 +104,11 @@ jobs:
           echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> lib/.secrets.g.dart
+          echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
+          echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
           echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
+          echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
           echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
@@ -165,7 +116,6 @@ jobs:
           echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart
           echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
-          echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
           echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart
           echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart
           echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
@@ -178,39 +128,172 @@ jobs:
           echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
           echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
           echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart
-          echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar
+          echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dart
           echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
           echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart
-
-      - name: Rename app
+          # tests
+          echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const litecoinTestWalletSeeds =  '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinCashTestWalletSeeds =  '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const nanoTestWalletSeeds =  '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart
+          echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinTestWalletReceiveAddress =  '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const ethereumTestWalletReceiveAddress =  '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const litecoinTestWalletReceiveAddress =  '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const polygonTestWalletReceiveAddress =  '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const solanaTestWalletReceiveAddress =  '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const tronTestWalletReceiveAddress =  '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
+          echo "const moneroTestWalletBlockHeight =  '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart  
+      - name: prepare monero_c and cache
         run: |
-          echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties
+          export MONEROC_HASH=$(cat scripts/prepare_moneroc.sh | grep 'git checkout' | xargs | awk '{ print $3 }')
+          echo MONEROC_HASH=$MONEROC_HASH >> /etc/environment
+          mkdir -p "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
+          pushd scripts
+            ln -s "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c"
+            ./prepare_moneroc.sh
+          popd
+          pushd scripts/monero_c
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" || true
+            mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" || true
 
-      - name: Build
+            rm -rf "$PWD/contrib/depends/built" "$PWD/monero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
+            rm -rf "$PWD/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
+            mkdir -p contrib/depends || true
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" "$PWD/contrib/depends/built"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" "$PWD/monero/contrib/depends/built"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" "$PWD/wownero/contrib/depends/built"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" "$PWD/contrib/depends/sources"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" "$PWD/monero/contrib/depends/sources"
+            ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources"
+          popd
+
+      - name: Execute Build and Setup Commands
+        run: |
+          pushd scripts/linux
+            source ./app_env.sh cakewallet
+            ./app_config.sh
+          popd
+
+      - name: Build monero_c
+        run: |
+          pushd scripts/linux/
+            source ./app_env.sh cakewallet
+            ./build_monero_all.sh
+          popd
+
+      - name: Install Flutter dependencies
+        run: |
+          flutter pub get
+
+      - name: Build generated code
+        run: |
+          ./model_generator.sh async
+
+      - name: Generate localization
+        run: |
+          dart run tool/generate_localization.dart
+
+      - name: Build linux
         run: |
-          cd /opt/android/cake_wallet
           flutter build linux --release
 
-      - name: Prepare release zip file
+      - name: Compress release
         run: |
-          cd /opt/android/cake_wallet/build/linux/x64/release
-          zip -r ${{env.BRANCH_NAME}}.zip bundle
+          pushd build/linux/x64/release
+          zip -r cakewallet_linux.zip bundle
+          popd
 
-      - name: Upload Artifact
-        uses: kittaakos/upload-artifact-as-is@v0
+      - name: Upload Artifact to github
+        uses: actions/upload-artifact@v4
         with:
-          path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip
+          path: ${{ github.workspace }}/build/linux/x64/release/cakewallet_linux.zip
+          name: cakewallet_linux
 
-#        Just as an artifact would be enough
-#      - name: Send Test APK
-#        continue-on-error: true
-#        uses: adrey/slack-file-upload-action@1.0.5
-#        with:
-#          token: ${{ secrets.SLACK_APP_TOKEN }}
-#          path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip
-#          channel: ${{ secrets.SLACK_APK_CHANNEL }}
-#          title: "${{ env.BRANCH_NAME }}_linux.zip"
-#          filename: ${{ env.BRANCH_NAME }}_linux.zip
-#          initial_comment: ${{ github.event.head_commit.message }}
+      - name: Prepare virtual desktop
+        if: ${{ contains(github.event.head_commit.message, 'run tests') }}
+        run: |
+            nohup Xvfb :99 -screen 0 720x1280x16 &
+            echo DISPLAY=:99 | sudo tee -a $GITHUB_ENV
+            dbus-daemon --system --fork
+            nohup NetworkManager &
+            nohup ffmpeg -framerate 60 -video_size 720x1280 -f x11grab -i :99 -c:v libx264 -c:a aac /opt/screen_grab.mkv &
+
+      # Note for people adding tests:
+      # - Tests are ran on Linux, with some things being mocked out.
+      # - Screen recording is being provided for the entire length of the test, you can download it in github articats.
+      # - Screen recordeding is encrypted, look at step "Stop screen recording, encrypt and upload", and add your key if you want
+      #   Reason for encryption is the fact that we restore the wallet from seed, and we don't want to leak that, while there
+      #   isn't much in those wallets anyway, we still wouldn't like to leak it to anyone who is able to access github.
+
+      - name: Test [confirm_seeds_flow_test]
+        if: ${{ contains(github.event.head_commit.message, 'run tests') }}
+        timeout-minutes: 20
+        run: |
+          xmessage -timeout 30 "confirm_seeds_flow_test" &
+          rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
+          exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/confirm_seeds_flow_test.dart
+      - name: Test [create_wallet_flow_test]
+        if: ${{ contains(github.event.head_commit.message, 'run tests') }}
+        timeout-minutes: 20
+        run: |
+          xmessage -timeout 30 "create_wallet_flow_test" &
+          rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
+          exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/create_wallet_flow_test.dart
+      - name: Test [exchange_flow_test]
+        if: ${{ contains(github.event.head_commit.message, 'run tests') }}
+        timeout-minutes: 20
+        run: |
+          xmessage -timeout 30 "exchange_flow_test" &
+          rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
+          exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/exchange_flow_test.dart
+      - name: Test [restore_wallet_through_seeds_flow_test]
+        if: ${{ contains(github.event.head_commit.message, 'run tests') }}
+        timeout-minutes: 20
+        run: |
+          xmessage -timeout 30 "restore_wallet_through_seeds_flow_test" &
+          rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
+          exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
+      - name: Stop screen recording, encrypt and upload
+        if: always()
+        run: |
+          if [[ ! -f "/opt/screen_grab.mkv" ]];
+          then
+            exit 0;
+          fi
+          killall ffmpeg
+          sleep 5
+          killall -9 ffmpeg || true
+          sleep 5
+          # Feel free to add your own public key if you wish
+          gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 6B3199AD9B3D23B8 # konstantin@cakewallet.com
+          gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 35C8DBAFB8D9ACAC # cyjan@mrcyjanek.net
+          gpg --trust-model always --encrypt --output /opt/screen_grab.mkv.gpg \
+            --recipient 6B3199AD9B3D23B8 \
+            --recipient 35C8DBAFB8D9ACAC \
+            /opt/screen_grab.mkv
+          rm /opt/screen_grab.mkv
+          mv /opt/screen_grab.mkv.gpg ./screen_grab.mkv.gpg
+      - name: Upload Artifact to github
+        if: always()
+        continue-on-error: true
+        uses: actions/upload-artifact@v4
+        with:
+          path: ${{ github.workspace }}/screen_grab.mkv.gpg
+          name: tests_screen_grab
diff --git a/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml b/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml
index 00d924171..c8bd4b26c 100644
--- a/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml
+++ b/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml
@@ -2,4 +2,5 @@
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
     <background android:drawable="@mipmap/ic_launcher_adaptive_back"/>
     <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/>
+    <monochrome android:drawable="@mipmap/ic_launcher_adaptive_mono"/>
 </adaptive-icon>
\ No newline at end of file
diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..27f939b41
Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..7bdb298c1
Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..79e9df08d
Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..0bb1c7430
Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..205f2ad2a
Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml b/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml
index 00d924171..c8bd4b26c 100644
--- a/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml
+++ b/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml
@@ -2,4 +2,5 @@
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
     <background android:drawable="@mipmap/ic_launcher_adaptive_back"/>
     <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/>
+    <monochrome android:drawable="@mipmap/ic_launcher_adaptive_mono"/>
 </adaptive-icon>
\ No newline at end of file
diff --git a/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..af8126ea9
Binary files /dev/null and b/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..0778b841f
Binary files /dev/null and b/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..318914c59
Binary files /dev/null and b/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..b1165abe8
Binary files /dev/null and b/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png differ
diff --git a/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png
new file mode 100644
index 000000000..ea11a01d3
Binary files /dev/null and b/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png differ
diff --git a/build-guide-linux.md b/build-guide-linux.md
index 99c2ed0c8..df5f0f601 100644
--- a/build-guide-linux.md
+++ b/build-guide-linux.md
@@ -115,7 +115,7 @@ Install Flutter package dependencies with this command:
 > `$ ./cakewallet.sh`
 > and back to project root directory:
 > `$ cd ../..`
-> and fetch dependecies again
+> and fetch dependencies again
 > `$ flutter pub get`
 
 Your CakeWallet binary will be built with some specific keys for iterate with 3rd party services. You may generate these secret keys placeholders with the following command:
diff --git a/build-guide-win.md b/build-guide-win.md
index 6ace961af..8cfd02c4c 100644
--- a/build-guide-win.md
+++ b/build-guide-win.md
@@ -16,14 +16,14 @@ These steps will help you configure and execute a build of CakeWallet from its s
 ### 1. Installing Package Dependencies
 
 For build CakeWallet windows application from sources you will be needed to have:
-> [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windwos`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`.
+> [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windows`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`.
 > [Install WSL] for building monero dependencies need to install Windows WSL (https://learn.microsoft.com/en-us/windows/wsl/install) and required packages for WSL (Ubuntu):
 `$ sudo apt update `
 `$ sudo apt build-essential cmake gcc-mingw-w64 g++-mingw-w64 autoconf libtool pkg-config`
 
 ### 2. Pull CakeWallet source code
 
-You can downlaod CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command:
+You can download CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command:
 `$ git clone https://github.com/cake-tech/cake_wallet.git --branch MrCyjaneK-cyjan-monerodart`
 OR you can download it as [Zip archive](https://github.com/cake-tech/cake_wallet/archive/refs/heads/MrCyjaneK-cyjan-monerodart.zip)
 
diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart
index 9eedcb134..d6063069c 100644
--- a/cw_monero/lib/api/wallet.dart
+++ b/cw_monero/lib/api/wallet.dart
@@ -9,6 +9,8 @@ import 'package:flutter/foundation.dart';
 import 'package:monero/monero.dart' as monero;
 import 'package:mutex/mutex.dart';
 
+bool debugMonero = false;
+
 int getSyncingHeight() {
   // final height = monero.MONERO_cw_WalletListener_height(getWlptr());
   final h2 = monero.Wallet_blockChainHeight(wptr!);
@@ -148,7 +150,7 @@ Future<bool> setupNodeSync(
     }
   }
 
-  if (kDebugMode) {
+  if (kDebugMode && debugMonero) {
     monero.Wallet_init3(
       wptr!,
       argv0: '',
diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart
index 99c821fa7..e46e18b9f 100644
--- a/cw_monero/lib/monero_wallet.dart
+++ b/cw_monero/lib/monero_wallet.dart
@@ -257,6 +257,9 @@ abstract class MoneroWalletBase
   }
 
   bool needExportOutputs(int amount) {
+    if (int.tryParse(monero.Wallet_secretSpendKey(wptr!)) != 0) {
+      return false;
+    }
     // viewOnlyBalance - balance that we can spend
     // TODO(mrcyjanek): remove hasUnknownKeyImages when we cleanup coin control
     return (monero.Wallet_viewOnlyBalance(wptr!, accountIndex: walletAddresses.account!.id) <
diff --git a/integration_test/components/common_test_cases.dart b/integration_test/components/common_test_cases.dart
index 83bbb0449..cc1e6d6d7 100644
--- a/integration_test/components/common_test_cases.dart
+++ b/integration_test/components/common_test_cases.dart
@@ -32,6 +32,11 @@ class CommonTestCases {
     expect(textWidget, hasWidget ? findsOneWidget : findsNothing);
   }
 
+  void hasTextAtLestOnce(String text, {bool hasWidget = true}) {
+    final textWidget = find.text(text);
+    expect(textWidget, hasWidget ? findsAny : findsNothing);
+  }
+
   void hasType<T>() {
     final typeWidget = find.byType(T);
     expect(typeWidget, findsOneWidget);
diff --git a/integration_test/components/common_test_flows.dart b/integration_test/components/common_test_flows.dart
index 8350b5859..c9e605339 100644
--- a/integration_test/components/common_test_flows.dart
+++ b/integration_test/components/common_test_flows.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
 import 'package:cake_wallet/entities/seed_type.dart';
 import 'package:cake_wallet/reactions/bip39_wallet_utils.dart';
 import 'package:cake_wallet/wallet_types.g.dart';
@@ -85,6 +87,7 @@ class CommonTestFlows {
     await _confirmPreSeedInfo();
 
     await _confirmWalletDetails();
+    await _commonTestCases.defaultSleepTime();
   }
 
   //* ========== Handles flow from welcome to restoring wallet from seeds ===============
@@ -168,8 +171,8 @@ class CommonTestFlows {
     await _walletListPageRobot.navigateToRestoreWalletOptionsPage();
     await _commonTestCases.defaultSleepTime();
 
-    await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
-    await _commonTestCases.defaultSleepTime();
+    if (!Platform.isLinux) await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
+    if (!Platform.isLinux) await _commonTestCases.defaultSleepTime();
 
     await _selectWalletTypeForWallet(walletType);
     await _commonTestCases.defaultSleepTime();
@@ -180,6 +183,7 @@ class CommonTestFlows {
 
   //* ========== Handles setting up pin code for wallet on first install ===============
   Future<void> setupPinCodeForWallet(List<int> pin) async {
+    if (Platform.isLinux) return;
     // ----------- SetupPinCode Page -------------
     // Confirm initial defaults - Widgets to be displayed etc
     await _setupPinCodeRobot.isSetupPinCodePage();
@@ -212,7 +216,7 @@ class CommonTestFlows {
 
     await _welcomePageRobot.navigateToRestoreWalletPage();
 
-    await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
+    if (!Platform.isLinux) await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
 
     await _selectWalletTypeForWallet(walletTypeToRestore);
   }
@@ -234,6 +238,12 @@ class CommonTestFlows {
 
     await _newWalletPageRobot.generateWalletName();
 
+    if (Platform.isLinux) {
+      // manual pin input
+      await _restoreFromSeedOrKeysPageRobot.enterPasswordForWalletRestore(CommonTestConstants.pin.join(""));
+      await _restoreFromSeedOrKeysPageRobot.enterPasswordRepeatForWalletRestore(CommonTestConstants.pin.join(""));
+    }
+
     await _newWalletPageRobot.onNextButtonPressed();
   }
 
@@ -252,11 +262,15 @@ class CommonTestFlows {
 
     _walletSeedPageRobot.confirmWalletSeedReminderDisplays();
 
-    await _walletSeedPageRobot.onCopySeedsButtonPressed();
+    // await _walletSeedPageRobot.onCopySeedsButtonPressed();
 
-    await _walletSeedPageRobot.onNextButtonPressed();
-
-    await _walletSeedPageRobot.onConfirmButtonOnSeedAlertDialogPressed();
+    await _walletSeedPageRobot.onSeedPageVerifyButtonPressed();
+    // Turns out the popup about "Copied to clipboard" prevents
+    //the button from being pressed on the first try, by just
+    //tapping it again we fix it.
+    // await _walletSeedPageRobot.onSeedPageVerifyButtonPressed();
+    
+    await _walletSeedPageRobot.onOpenWalletButtonPressed();
   }
 
   //* Main Restore Actions - On the RestoreFromSeed/Keys Page - Restore from Seeds Action
@@ -277,6 +291,12 @@ class CommonTestFlows {
           .enterBlockHeightForWalletRestore(secrets.moneroTestWalletBlockHeight);
     }
 
+    if (Platform.isLinux) {
+      // manual pin input
+      await _restoreFromSeedOrKeysPageRobot.enterPasswordForWalletRestore(CommonTestConstants.pin.join(""));
+      await _restoreFromSeedOrKeysPageRobot.enterPasswordRepeatForWalletRestore(CommonTestConstants.pin.join(""));
+    }
+
     await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
   }
 
diff --git a/integration_test/funds_related_tests.dart b/integration_test/funds_related_tests.dart
index db24fbc0b..27187dc2f 100644
--- a/integration_test/funds_related_tests.dart
+++ b/integration_test/funds_related_tests.dart
@@ -67,6 +67,11 @@ void main() {
         await authPageRobot.enterPinCode(CommonTestConstants.pin);
       }
 
+      final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
+      if (onAuthPageDesktop) {
+        await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
+      }
+
       // ----------- Exchange Confirm Page -------------
       await exchangeConfirmPageRobot.isExchangeConfirmPage();
 
diff --git a/integration_test/robots/auth_page_robot.dart b/integration_test/robots/auth_page_robot.dart
index 6358d4398..2f5c43627 100644
--- a/integration_test/robots/auth_page_robot.dart
+++ b/integration_test/robots/auth_page_robot.dart
@@ -20,6 +20,11 @@ class AuthPageRobot extends PinCodeWidgetRobot {
     return hasPin;
   }
 
+  bool onAuthPageDesktop() {
+    final hasWalletPasswordInput = find.byKey(ValueKey('enter_wallet_password'));
+    return hasWalletPasswordInput.tryEvaluate();
+  }
+
   Future<void> isAuthPage() async {
     await commonTestCases.isSpecificPage<AuthPage>();
   }
diff --git a/integration_test/robots/pin_code_widget_robot.dart b/integration_test/robots/pin_code_widget_robot.dart
index 18dc5fba4..62e606703 100644
--- a/integration_test/robots/pin_code_widget_robot.dart
+++ b/integration_test/robots/pin_code_widget_robot.dart
@@ -24,6 +24,20 @@ class PinCodeWidgetRobot {
     commonTestCases.hasValueKey('pin_code_button_0_key');
   }
 
+  Future<void> enterPassword(String password, {int pumpDuration = 100}) async {
+    await commonTestCases.enterText(
+      password,
+      'enter_wallet_password',
+    );
+    await tester.pumpAndSettle();
+    await commonTestCases.tapItemByKey(
+      'unlock',
+    );
+    await tester.pumpAndSettle();
+
+    await commonTestCases.defaultSleepTime();
+  }
+
   Future<void> enterPinCode(List<int> pinCode, {int pumpDuration = 100}) async {
     for (int pin in pinCode) {
       await commonTestCases.tapItemByKey(
diff --git a/integration_test/robots/restore_from_seed_or_key_robot.dart b/integration_test/robots/restore_from_seed_or_key_robot.dart
index 9d973061b..015a9e46f 100644
--- a/integration_test/robots/restore_from_seed_or_key_robot.dart
+++ b/integration_test/robots/restore_from_seed_or_key_robot.dart
@@ -1,7 +1,9 @@
 import 'package:cake_wallet/entities/seed_type.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
+import 'package:cake_wallet/src/widgets/seed_widget.dart';
 import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import '../components/common_test_cases.dart';
@@ -65,12 +67,28 @@ class RestoreFromSeedOrKeysPageRobot {
 
   Future<void> enterSeedPhraseForWalletRestore(String text) async {
     ValidatableAnnotatedEditableTextState seedTextState =
-        await tester.state(find.byType(ValidatableAnnotatedEditableText));
+      await tester.state(find.byType(ValidatableAnnotatedEditableText));
 
     seedTextState.widget.controller.text = text;
     await tester.pumpAndSettle();
   }
 
+  Future<void> enterPasswordForWalletRestore(String text) async {
+    await commonTestCases.enterText(
+      text,
+      'password',
+    );
+    await tester.pumpAndSettle();
+  }
+
+  Future<void> enterPasswordRepeatForWalletRestore(String text) async {
+    await commonTestCases.enterText(
+      text,
+      'repeat_wallet_password',
+    );
+    await tester.pumpAndSettle();
+  }
+
   Future<void> enterBlockHeightForWalletRestore(String blockHeight) async {
     await commonTestCases.enterText(
       blockHeight,
diff --git a/integration_test/robots/send_page_robot.dart b/integration_test/robots/send_page_robot.dart
index f8e1a49ad..b705c803f 100644
--- a/integration_test/robots/send_page_robot.dart
+++ b/integration_test/robots/send_page_robot.dart
@@ -183,32 +183,15 @@ class SendPageRobot {
   }
 
   Future<void> _handleAuthPage() async {
-    tester.printToConsole('Inside _handleAuth');
-    await tester.pump();
-    tester.printToConsole('starting auth checks');
-
-    final authPage = authPageRobot.onAuthPage();
-
-    tester.printToConsole('hasAuth:$authPage');
-
-    if (authPage) {
-      await tester.pump();
-      tester.printToConsole('Starting inner _handleAuth loop checks');
-
-      try {
-        await authPageRobot.enterPinCode(CommonTestConstants.pin, pumpDuration: 500);
-        tester.printToConsole('Auth done');
-
-        await tester.pump();
-
-        tester.printToConsole('Auth pump done');
-      } catch (e) {
-        tester.printToConsole('Auth failed, retrying');
-        await tester.pump();
-        _handleAuthPage();
-      }
+    final onAuthPage = authPageRobot.onAuthPage();
+    if (onAuthPage) {
+      await authPageRobot.enterPinCode(CommonTestConstants.pin);
+    }
+
+  final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
+  if (onAuthPageDesktop) {
+      await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
     }
-    await tester.pump();
   }
 
   Future<void> handleSendResult() async {
@@ -221,7 +204,7 @@ class SendPageRobot {
 
     tester.printToConsole('Has an Error in the handle: $hasError');
 
-    int maxRetries = 20;
+    int maxRetries = 3;
     int retries = 0;
 
     while (hasError && retries < maxRetries) {
diff --git a/integration_test/robots/wallet_seed_page_robot.dart b/integration_test/robots/wallet_seed_page_robot.dart
index d52f3b1ec..576bff0d6 100644
--- a/integration_test/robots/wallet_seed_page_robot.dart
+++ b/integration_test/robots/wallet_seed_page_robot.dart
@@ -14,8 +14,13 @@ class WalletSeedPageRobot {
     await commonTestCases.isSpecificPage<WalletSeedPage>();
   }
 
-  Future<void> onNextButtonPressed() async {
-    await commonTestCases.tapItemByKey('wallet_seed_page_next_button_key');
+  Future<void> onSeedPageVerifyButtonPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_verify_seed_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> onOpenWalletButtonPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_open_wallet_button_key');
     await commonTestCases.defaultSleepTime();
   }
 
@@ -38,11 +43,14 @@ class WalletSeedPageRobot {
     final walletSeeds = walletSeedViewModel.seed;
 
     commonTestCases.hasText(walletName);
-    commonTestCases.hasText(walletSeeds);
+    final seedList = walletSeeds.trim().split(" ");
+    for (final seedWord in seedList) {
+      commonTestCases.hasTextAtLestOnce(seedWord);
+    }
   }
 
   void confirmWalletSeedReminderDisplays() {
-    commonTestCases.hasText(S.current.seed_reminder);
+    commonTestCases.hasText(S.current.cake_seeds_save_disclaimer);
   }
 
   Future<void> onSaveSeedsButtonPressed() async {
diff --git a/integration_test/test_suites/confirm_seeds_flow_test.dart b/integration_test/test_suites/confirm_seeds_flow_test.dart
index 2d11a2cc4..a62ce3f60 100644
--- a/integration_test/test_suites/confirm_seeds_flow_test.dart
+++ b/integration_test/test_suites/confirm_seeds_flow_test.dart
@@ -1,9 +1,13 @@
+import 'dart:io';
+
 import 'package:cake_wallet/wallet_types.g.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:integration_test/integration_test.dart';
 
+import '../components/common_test_cases.dart';
 import '../components/common_test_constants.dart';
 import '../components/common_test_flows.dart';
 import '../robots/auth_page_robot.dart';
@@ -95,6 +99,10 @@ Future<void> _confirmSeedsFlowForWalletType(
     await authPageRobot.enterPinCode(CommonTestConstants.pin);
   }
 
+  final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
+  if (onAuthPageDesktop) {
+    await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
+  }
   await tester.pumpAndSettle();
 
   await walletKeysAndSeedPageRobot.isWalletKeysAndSeedPage();
diff --git a/integration_test/test_suites/exchange_flow_test.dart b/integration_test/test_suites/exchange_flow_test.dart
index c36ef9396..8ec2e54e7 100644
--- a/integration_test/test_suites/exchange_flow_test.dart
+++ b/integration_test/test_suites/exchange_flow_test.dart
@@ -56,6 +56,10 @@ void main() {
       await authPageRobot.enterPinCode(CommonTestConstants.pin);
     }
 
+    final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
+    if (onAuthPageDesktop) {
+      await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
+    }
     await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed();
     await exchangeTradePageRobot.onGotItButtonPressed();
   });
diff --git a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
index a810aa722..0589d16ba 100644
--- a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
+++ b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
@@ -1,4 +1,7 @@
+import 'dart:io';
+
 import 'package:cake_wallet/wallet_types.g.dart';
+import 'package:cw_core/utils/print_verbose.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
diff --git a/integration_test_runner.sh b/integration_test_runner.sh
index 34c9227c0..86e28f0b8 100755
--- a/integration_test_runner.sh
+++ b/integration_test_runner.sh
@@ -1,4 +1,5 @@
 #!/bin/bash
+export DESKTOP_FORCE_MOBILE="Y"
 
 declare -a targets
 declare -a passed_tests
@@ -12,6 +13,10 @@ done < <(find integration_test/test_suites -name "*.dart" -type f -print0)
 # Run each test and collect results
 for target in "${targets[@]}"
 do
+    if [[ "x$REMOVE_DATA_DIRECTORY" == "xY" ]];
+    then
+        rm -rf ~/.local/share/com.example.cake_wallet ~/Documents/cake_wallet
+    fi
     echo "Running test: $target"
     if flutter drive \
       --driver=test_driver/integration_test.dart \
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index 25140f106..049bfa15c 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -334,20 +334,20 @@ Future<void> defaultSettingsMigration(
           );
           break;
         case 46:
-          _fixNodesUseSSLFlag(nodes);
-          updateWalletTypeNodesWithNewNode(
+          await _fixNodesUseSSLFlag(nodes);
+          await updateWalletTypeNodesWithNewNode(
             newNodeUri: 'litecoin.stackwallet.com:20063',
             nodes: nodes,
             type: WalletType.litecoin,
             useSSL: true,
           );
-          updateWalletTypeNodesWithNewNode(
+          await updateWalletTypeNodesWithNewNode(
             newNodeUri: 'electrum-ltc.bysh.me:50002',
             nodes: nodes,
             type: WalletType.litecoin,
             useSSL: true,
           );
-          _changeDefaultNode(
+          await _changeDefaultNode(
             nodes: nodes,
             sharedPreferences: sharedPreferences,
             type: WalletType.solana,
@@ -360,13 +360,13 @@ Future<void> defaultSettingsMigration(
               'solana-rpc.publicnode.com:443',
             ],
           );
-          _updateNode(
+          await _updateNode(
             nodes: nodes,
             currentUri: "ethereum.publicnode.com",
             newUri: "ethereum-rpc.publicnode.com",
             useSSL: true,
           );
-          _updateNode(
+          await _updateNode(
             nodes: nodes,
             currentUri: "polygon-bor.publicnode.com",
             newUri: "polygon-bor-rpc.publicnode.com",
@@ -387,12 +387,12 @@ Future<void> defaultSettingsMigration(
   await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
 }
 
-void _updateNode({
+Future<void> _updateNode({
   required Box<Node> nodes,
   required String currentUri,
   String? newUri,
   bool? useSSL,
-}) {
+}) async {
   for (Node node in nodes.values) {
     if (node.uriRaw == currentUri) {
       if (newUri != null) {
@@ -401,6 +401,7 @@ void _updateNode({
       if (useSSL != null) {
         node.useSSL = useSSL;
       }
+      await node.save();
     }
   }
 }
@@ -481,7 +482,7 @@ void _deselectExchangeProvider(SharedPreferences sharedPreferences, String provi
   );
 }
 
-void _fixNodesUseSSLFlag(Box<Node> nodes) {
+Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async {
   for (Node node in nodes.values) {
     switch (node.uriRaw) {
       case cakeWalletLitecoinElectrumUri:
@@ -490,6 +491,7 @@ void _fixNodesUseSSLFlag(Box<Node> nodes) {
       case newCakeWalletMoneroUri:
         node.useSSL = true;
         node.trusted = true;
+        await node.save();
     }
   }
 }
diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart
index e63a01f61..e2d5a953c 100644
--- a/lib/src/screens/new_wallet/new_wallet_page.dart
+++ b/lib/src/screens/new_wallet/new_wallet_page.dart
@@ -221,6 +221,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
                           ),
                           if (_walletNewVM.hasWalletPassword) ...[
                             TextFormField(
+                              key: ValueKey('password'),
                               onChanged: (value) => _walletNewVM.walletPassword = value,
                               controller: _passwordController,
                               textAlign: TextAlign.center,
@@ -257,6 +258,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
                               ),
                             ),
                             TextFormField(
+                              key: ValueKey('repeat_wallet_password'),
                               onChanged: (value) => _walletNewVM.repeatedWalletPassword = value,
                               controller: _repeatedPasswordController,
                               textAlign: TextAlign.center,
diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart
index 83772f866..0c9af6910 100644
--- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart
+++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart
@@ -148,12 +148,14 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
             ),
             if (widget.displayWalletPassword)
               ...[Container(
+                  key: ValueKey('password'),
                   padding: EdgeInsets.only(top: 20.0),
                   child: BaseTextFormField(
                     controller: passwordTextEditingController,
                     hintText: S.of(context).password,
                     obscureText: true)),
                 Container(
+                  key: ValueKey('repeat_wallet_password'),
                   padding: EdgeInsets.only(top: 20.0),
                   child: BaseTextFormField(
                     controller: repeatedPasswordTextEditingController,
diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart
index 1684f6f92..6a493087b 100644
--- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart
+++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart
@@ -223,12 +223,14 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
             ),
           if (widget.displayWalletPassword)
             ...[BaseTextFormField(
+                key: ValueKey('password'),
                 controller: passwordTextEditingController,
                 hintText: S
                     .of(context)
                     .password,
                 obscureText: true),
               BaseTextFormField(
+                  key: ValueKey('repeat_wallet_password'),
                   controller: repeatedPasswordTextEditingController,
                   hintText: S
                       .of(context)
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index a52bd11e9..2d64c55a3 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -525,6 +525,10 @@ class SendPage extends BasePage {
       if (state is TransactionCommitted) {
         WidgetsBinding.instance.addPostFrameCallback((_) async {
 
+          if (!context.mounted) {
+            return;
+          }
+
           final successMessage = S.of(context).send_success(
               sendViewModel.selectedCryptoCurrency.toString());
 
diff --git a/lib/src/screens/wallet_unlock/wallet_unlock_page.dart b/lib/src/screens/wallet_unlock/wallet_unlock_page.dart
index 3e6966f9d..4afbfe2c1 100644
--- a/lib/src/screens/wallet_unlock/wallet_unlock_page.dart
+++ b/lib/src/screens/wallet_unlock/wallet_unlock_page.dart
@@ -170,6 +170,7 @@ class WalletUnlockPageState extends AuthPageState<WalletUnlockPage> {
                     SizedBox(height: 24),
                     Form(
                       child: TextFormField(
+                        key: ValueKey('enter_wallet_password'),
                         onChanged: (value) => null,
                         controller: _passwordController,
                         textAlign: TextAlign.center,
@@ -205,6 +206,7 @@ class WalletUnlockPageState extends AuthPageState<WalletUnlockPage> {
                 ),
               ),
               Padding(
+                key: ValueKey('unlock'),
                 padding: EdgeInsets.only(bottom: 24),
                 child: Observer(
                   builder: (_) => LoadingPrimaryButton(
diff --git a/linux/my_application.cc b/linux/my_application.cc
index 49ed75499..49f9ae139 100644
--- a/linux/my_application.cc
+++ b/linux/my_application.cc
@@ -46,8 +46,11 @@ static void my_application_activate(GApplication* application) {
   } else {
     gtk_window_set_title(window, "Cake Wallet");
   }
-
-  gtk_window_set_default_size(window, 1280, 720);
+  if (getenv("DESKTOP_FORCE_MOBILE")) {
+    gtk_window_set_default_size(window, 720, 1280);
+  } else {
+    gtk_window_set_default_size(window, 1280, 720);
+  }
   gtk_widget_show(GTK_WIDGET(window));
 
   g_autoptr(FlDartProject) project = fl_dart_project_new();
diff --git a/model_generator.sh b/model_generator.sh
index 730817c24..1443b0fc9 100755
--- a/model_generator.sh
+++ b/model_generator.sh
@@ -1,18 +1,24 @@
 #!/bin/bash
 set -x -e
 
-cd cw_core; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_evm; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_monero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_bitcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_haven; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_nano; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_bitcoin_cash; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_solana; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_tron; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_wownero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
-cd cw_polygon; flutter pub get; cd ..
-cd cw_ethereum; flutter pub get; cd ..
-cd cw_mweb && flutter pub get && cd ..
-dart run build_runner build --delete-conflicting-outputs
+for cwcoin in cw_{core,evm,monero,bitcoin,haven,nano,bitcoin_cash,solana,tron,wownero}
+do
+    if [[ "x$1" == "xasync" ]];
+    then
+        bash -c "cd $cwcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .." &
+    else
+        bash -c "cd $cwcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .."
+    fi
+done
+for cwcoin in cw_{polygon,ethereum,mwebd};
+do        
+    if [[ "x$1" == "xasync" ]];
+    then
+        bash -c "cd $cwcoin; flutter pub get; cd .." &
+    else
+        bash -c "cd $cwcoin; flutter pub get; cd .."
+    fi
+done
 
+flutter pub get
+dart run build_runner build --delete-conflicting-outputs
diff --git a/scripts/android/.gitignore b/scripts/android/.gitignore
new file mode 100644
index 000000000..f7e94b7c0
--- /dev/null
+++ b/scripts/android/.gitignore
@@ -0,0 +1 @@
+mwebd
\ No newline at end of file
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index 6b1907451..45e28379d 100644
--- a/scripts/android/app_env.sh
+++ b/scripts/android/app_env.sh
@@ -23,7 +23,7 @@ MONERO_COM_SCHEME="monero.com"
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="4.22.1"
-CAKEWALLET_BUILD_NUMBER=241
+CAKEWALLET_BUILD_NUMBER=242
 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
 CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
 CAKEWALLET_SCHEME="cakewallet"
diff --git a/scripts/android/build_monero_all.sh b/scripts/android/build_monero_all.sh
index 261ebd560..71a6b6228 100755
--- a/scripts/android/build_monero_all.sh
+++ b/scripts/android/build_monero_all.sh
@@ -8,50 +8,20 @@ cd "$(dirname "$0")"
 
 NPROC="-j$(nproc)"
 
-if [[ "x$(uname)" == "xDarwin" ]];
-then
-    USE_DOCKER="ON"
-    NPROC="-j1"
-fi
-
 ../prepare_moneroc.sh
 
-if [[ ! "x$RUNNER_OS" == "x" ]];
-then
-    REMOVE_CACHES=ON
-fi
-
-# NOTE: -j1 is intentional. Otherwise you will run into weird behaviour on macos
-if [[ ! "x$USE_DOCKER" == "x" ]];
-then
-    for COIN in monero wownero;
-    do
-        pushd ../monero_c
-            docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} x86_64-linux-android $NPROC"
-            # docker run --platform linux/amd64 -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} i686-linux-android $NPROC"
-            docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} armv7a-linux-androideabi $NPROC"
-            docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} aarch64-linux-android $NPROC"
-        popd
-    done
-else
-    for COIN in monero wownero;
-    do
-        pushd ../monero_c
-            env -i ./build_single.sh ${COIN} x86_64-linux-android $NPROC
-            [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/x86_64-linux-android
-            # ./build_single.sh ${COIN} i686-linux-android $NPROC
-            # [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/i686-linux-android
-            env -i ./build_single.sh ${COIN} armv7a-linux-androideabi $NPROC
-            [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/armv7a-linux-androideabi
-            env -i ./build_single.sh ${COIN} aarch64-linux-android $NPROC
-            [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/aarch64-linux-android
-
-        popd
-        unxz -f ../monero_c/release/${COIN}/x86_64-linux-android_libwallet2_api_c.so.xz
-
-        unxz -f ../monero_c/release/${COIN}/armv7a-linux-androideabi_libwallet2_api_c.so.xz
-
-        unxz -f ../monero_c/release/${COIN}/aarch64-linux-android_libwallet2_api_c.so.xz
-        [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/{built,sources}
-    done
-fi
+for COIN in monero wownero;
+do
+    pushd ../monero_c
+        for target in {x86_64,aarch64}-linux-android armv7a-linux-androideabi
+        do
+            if [[ -f "release/${COIN}/${target}_libwallet2_api_c.so" ]];
+            then
+                echo "file exist, not building monero_c for ${COIN}/$target.";
+            else
+                env -i ./build_single.sh ${COIN} $target $NPROC
+                unxz -f ../monero_c/release/${COIN}/${target}_libwallet2_api_c.so.xz
+            fi
+        done
+    popd
+done
\ No newline at end of file
diff --git a/scripts/android/build_mwebd.sh b/scripts/android/build_mwebd.sh
index 4434e30f1..cd4e2c1f4 100755
--- a/scripts/android/build_mwebd.sh
+++ b/scripts/android/build_mwebd.sh
@@ -16,7 +16,4 @@ cd mwebd
 git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f
 gomobile bind -target=android -androidapi 21 .
 mkdir -p ../../../cw_mweb/android/libs/
-mv ./mwebd.aar $_
-# cleanup:
-cd ..
-rm -rf mwebd
\ No newline at end of file
+cp ./mwebd.aar $_
\ No newline at end of file
diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh
index c1747c502..079b12391 100644
--- a/scripts/ios/app_env.sh
+++ b/scripts/ios/app_env.sh
@@ -19,7 +19,7 @@ MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="4.22.1"
-CAKEWALLET_BUILD_NUMBER=288
+CAKEWALLET_BUILD_NUMBER=289
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 HAVEN_NAME="Haven"
diff --git a/scripts/linux/Dockerfile.linux b/scripts/linux/Dockerfile.linux
new file mode 100644
index 000000000..c8f4d3bde
--- /dev/null
+++ b/scripts/linux/Dockerfile.linux
@@ -0,0 +1,148 @@
+# Usage:
+# docker build . -f Dockerfile.linux -t ghcr.io/cake-tech/cake_wallet:main-linux
+# docker push ghcr.io/cake-tech/cake_wallet:main-linux
+
+FROM --platform=linux/amd64 docker.io/debian:12
+
+LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet
+
+ENV GOLANG_VERSION=1.23.4
+# comes from https://developer.android.com/studio/#command-tools
+ENV ANDROID_SDK_TOOLS_VERSION=11076708
+# https://developer.android.com/studio/releases/build-tools
+ENV ANDROID_PLATFORM_VERSION=34
+ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0
+
+ENV FLUTTER_VERSION=3.24.0
+
+# If we ever need to migrate the home directory...
+RUN sed -i 's|^root:[^:]*:[^:]*:[^:]*:[^:]*:/root:|root:x:0:0:root:/root:|' /etc/passwd
+# mkdir -p /root && rm -rf /root && cp -a /root /root
+ENV HOME=/root
+# Heavily inspired by cirrusci images
+# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/tools/Dockerfile
+# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34/Dockerfile
+# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34-ndk/Dockerfile
+# https://github.com/cirruslabs/docker-images-flutter/blob/master/sdk/Dockerfile
+
+ENV ANDROID_HOME=/opt/android-sdk-linux \
+    LANG=en_US.UTF-8 \
+    LC_ALL=en_US.UTF-8 \
+    LANGUAGE=en_US:en
+
+ENV ANDROID_SDK_ROOT=$ANDROID_HOME \
+    PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator
+
+RUN set -o xtrace \
+    && cd /opt \
+    && apt-get update \
+    && apt-get upgrade -y \
+    && apt-get install -y jq \
+    && apt-get install -y default-jdk \
+    && apt-get install -y sudo wget zip unzip git openssh-client curl bc software-properties-common build-essential ruby-full ruby-bundler libstdc++6 libpulse0 libglu1-mesa locales lcov libsqlite3-dev --no-install-recommends \
+    # for x86 emulators
+    && apt-get install -y libxtst6 libnss3-dev libnspr4 libxss1 libatk-bridge2.0-0 libgtk-3-0 libgdk-pixbuf2.0-0 \
+    && apt-get install -y -qq xxd \
+    && apt-get install -y lftp \
+    && apt-get install -qq -y sqlite3 libsqlite3-dev \
+    # linux desktop dependencies
+    && apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev \
+    # monero_c dependencies
+    && apt-get install -y ccache build-essential autoconf libtool gperf llvm \
+    # extra stuff for KVM
+    && apt-get install -y udev qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils \
+    # for linux tests
+    && apt-get install -y xvfb network-manager ffmpeg x11-utils \
+    && rm -rf /var/lib/apt/lists/* \
+    && sh -c 'echo "en_US.UTF-8 UTF-8" > /etc/locale.gen' \
+    && locale-gen \
+    && update-locale LANG=en_US.UTF-8
+
+# install nodejs for actions
+RUN apt-get update && \
+    apt-get install -y curl && \
+    curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \
+    apt-get install -y nodejs && \
+    apt-get clean && \
+    rm -rf /var/lib/apt/lists/*
+
+RUN wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz &&\
+    rm -rf /usr/local/go &&\
+    tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz
+
+ENV PATH=${PATH}:/usr/local/go/bin:${HOME}/go/bin
+ENV GOROOT=/usr/local/go
+ENV GOPATH=${HOME}/go
+RUN go install golang.org/x/mobile/cmd/gomobile@latest
+RUN gomobile init
+
+RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip -O android-sdk-tools.zip \
+    && mkdir -p ${ANDROID_HOME}/cmdline-tools/ \
+    && unzip -q android-sdk-tools.zip -d ${ANDROID_HOME}/cmdline-tools/ \
+    && mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \
+    && chown -R root:root $ANDROID_HOME \
+    && rm android-sdk-tools.zip \
+    && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
+    && yes | sdkmanager --licenses \
+    && wget -O /usr/bin/android-wait-for-emulator https://raw.githubusercontent.com/travis-ci/travis-cookbooks/master/community-cookbooks/android-sdk/files/default/android-wait-for-emulator \
+    && chmod +x /usr/bin/android-wait-for-emulator \
+    && sdkmanager platform-tools \
+    && mkdir -p ${HOME}/.android \
+    && touch ${HOME}/.android/repositories.cfg \
+    && git config --global user.email "czarek@cakewallet.com" \
+    && git config --global user.name "CakeWallet CI"
+
+# emulator is not available on linux/arm64 (https://issuetracker.google.com/issues/227219818)
+RUN if [ $(uname -m) == "x86_64" ]; then sdkmanager emulator ; fi
+
+# Extra dependencies to not download them for cake wallet build
+RUN yes | sdkmanager \
+    "platforms;android-$ANDROID_PLATFORM_VERSION" \
+    "build-tools;$ANDROID_BUILD_TOOLS_VERSION" \
+    "platforms;android-33" \
+    "build-tools;33.0.2" \
+    "build-tools;33.0.1" \
+    "build-tools;33.0.0" \
+    "build-tools;35.0.0"
+
+ENV ANDROID_NDK_VERSION=27.2.12479018
+
+# Extra ndk dependency for sp_scanner
+RUN yes | sdkmanager "ndk;$ANDROID_NDK_VERSION" \
+    "ndk;27.0.12077973"
+
+# https://github.com/ReactiveCircus/android-emulator-runner dependencies for tests
+RUN yes | sdkmanager "system-images;android-29;default;x86" \
+    "system-images;android-29;default;x86_64" \
+    "system-images;android-31;default;x86_64" \
+    "platforms;android-29"
+
+# fake the KVM status so android emulator doesn't complain (that much)
+RUN (addgroup kvm || true) && \
+    adduser root kvm && \
+    mkdir -p /etc/udev/rules.d/ && \
+    echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | tee /etc/udev/rules.d/99-kvm4all.rules
+
+ENV PATH=${HOME}/.cargo/bin:${PATH}
+
+RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
+    cargo install cargo-ndk && \
+    for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu; \
+    do \
+        rustup target add --toolchain stable $target; \
+    done
+
+
+ENV HOME=${HOME}
+ENV FLUTTER_HOME=${HOME}/sdks/flutter/${FLUTTER_VERSION}
+ENV FLUTTER_ROOT=$FLUTTER_HOME
+
+ENV PATH=${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin
+
+RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME}
+
+RUN yes | flutter doctor --android-licenses \
+    && flutter doctor \
+    && chown -R root:root ${FLUTTER_HOME}
+
+RUN flutter precache
diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh
index f0ec8e9e6..5103eeccc 100755
--- a/scripts/linux/app_env.sh
+++ b/scripts/linux/app_env.sh
@@ -15,7 +15,7 @@ fi
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="1.12.1"
-CAKEWALLET_BUILD_NUMBER=42
+CAKEWALLET_BUILD_NUMBER=43
 
 if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
     echo "Wrong app type."
diff --git a/scripts/linux/build_monero_all.sh b/scripts/linux/build_monero_all.sh
index 5dc512527..558423219 100755
--- a/scripts/linux/build_monero_all.sh
+++ b/scripts/linux/build_monero_all.sh
@@ -1,9 +1,5 @@
 #!/bin/bash
 
-
-. ./config.sh
-
-
 set -x -e
 
 cd "$(dirname "$0")"
@@ -15,7 +11,15 @@ NPROC="-j$(nproc)"
 for COIN in monero wownero;
 do
     pushd ../monero_c
-        ./build_single.sh ${COIN} $(gcc -dumpmachine) $NPROC
+        for target in x86_64-linux-gnu
+        do
+            if [[ -f "release/${COIN}/${target}_libwallet2_api_c.so" ]];
+            then
+                echo "file exist, not building monero_c for ${COIN}/$target.";
+            else
+                ./build_single.sh ${COIN} $target $NPROC
+                unxz -f ../monero_c/release/${COIN}/${target}_libwallet2_api_c.so.xz
+            fi
+        done
     popd
-    unxz -f ../monero_c/release/${COIN}/$(gcc -dumpmachine)_libwallet2_api_c.so.xz
-done
+done
\ No newline at end of file
diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh
index fe3d806d8..af2b6ab1e 100755
--- a/scripts/macos/app_env.sh
+++ b/scripts/macos/app_env.sh
@@ -22,7 +22,7 @@ MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="1.15.1"
-CAKEWALLET_BUILD_NUMBER=100
+CAKEWALLET_BUILD_NUMBER=101
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
diff --git a/scripts/prepare_moneroc.sh b/scripts/prepare_moneroc.sh
index c345408dd..c0de33f6f 100755
--- a/scripts/prepare_moneroc.sh
+++ b/scripts/prepare_moneroc.sh
@@ -4,9 +4,9 @@ set -x -e
 
 cd "$(dirname "$0")"
 
-if [[ ! -d "monero_c" ]];
+if [[ ! -d "monero_c/.git" ]];
 then
-    git clone https://github.com/mrcyjanek/monero_c --branch master
+    git clone https://github.com/mrcyjanek/monero_c --branch master monero_c
     cd monero_c
     git checkout af5277f96073917185864d3596e82b67bee54e78
     git reset --hard
diff --git a/scripts/windows/.gitignore b/scripts/windows/.gitignore
new file mode 100644
index 000000000..bb28076cd
--- /dev/null
+++ b/scripts/windows/.gitignore
@@ -0,0 +1 @@
+actions-runner
\ No newline at end of file
diff --git a/scripts/windows/Dockerfile.windows b/scripts/windows/Dockerfile.windows
new file mode 100644
index 000000000..f2a08b41c
--- /dev/null
+++ b/scripts/windows/Dockerfile.windows
@@ -0,0 +1,68 @@
+# Usage:
+# docker build . -f Dockerfile.windows -t ghcr.io/cake-tech/cake_wallet:main-windows
+# docker push ghcr.io/cake-tech/cake_wallet:main-windows
+
+FROM mcr.microsoft.com/windows/servercore:ltsc2022
+
+ENV FLUTTER_VERSION=3.24.0
+ENV GIT_VERSION=2.47.1
+ENV VS_INSTALLED_DIR="C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools"
+ENV PATH="C:\Users\ContainerAdministrator\.cargo\bin;C:\ProgramData\chocolatey\bin;C:\flutter\flutter\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps"
+ENV RUNNER_VERSION=2.321.0
+ENV RUNNER_URL=https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-win-x64-${RUNNER_VERSION}.zip
+ENV RUNNER_WORKDIR=_work
+
+RUN powershell -Command \
+    curl.exe -L https://aka.ms/vs/17/release/vc_redist.x64.exe -o vc_redist.x64.exe ; \
+    Start-Process -Wait -FilePath .\vc_redist.x64.exe -ArgumentList '/quiet', '/install' ; \
+    Remove-Item -Force vc_redist.x64.exe
+
+RUN powershell -Command \
+    $GIT_VERSION = [Environment]::GetEnvironmentVariable('GIT_VERSION'); \
+    curl.exe -L https://github.com/git-for-windows/git/releases/download/v$($GIT_VERSION).windows.1/Git-$($GIT_VERSION)-64-bit.exe -o git_installer.exe ; \
+    Start-Process -Wait -FilePath .\git_installer.exe -ArgumentList '/SILENT', '/NOICONS' ; \
+    Remove-Item -Force git_installer.exe
+
+RUN powershell -NoProfile -ExecutionPolicy Bypass -Command \
+    Set-ExecutionPolicy RemoteSigned -Scope Process; \
+    [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; \
+    Invoke-WebRequest https://chocolatey.org/install.ps1 -UseBasicP -OutFile install.ps1; \
+    powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1; \
+    Remove-Item -Force install.ps1
+
+RUN choco install -y visualstudio2022community
+RUN choco install -y visualstudio2022-workload-nativedesktop
+RUN choco install -y nodejs
+RUN choco install -y go
+RUN choco install -y 7zip
+
+RUN powershell -Command \
+    curl.exe -L https://win.rustup.rs -o rustup-init.exe; \
+    Start-Process -Wait -FilePath .\rustup-init.exe -ArgumentList "-y"; \
+    Remove-Item -Force .\rustup-init.exe
+
+RUN powershell -Command \
+    curl.exe -L https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -o C:\Windows\System32\nuget.exe
+
+RUN powershell -Command \
+    $FLUTTER_VERSION = [Environment]::GetEnvironmentVariable('FLUTTER_VERSION'); \
+    curl.exe -L https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_$($FLUTTER_VERSION)-stable.zip -o flutter.zip ; \
+    7z x flutter.zip -oC:\flutter -bsp1 -bse1 ; \
+    Remove-Item -Force flutter.zip
+
+RUN flutter precache
+
+WORKDIR C:\\actions-runner
+
+RUN powershell -Command \
+    curl.exe -L $env:RUNNER_URL -o 'actions-runner.zip'; \
+    7z x actions-runner.zip -oC:\actions-runner -bsp1 -bse1 ; \
+    Remove-Item -Path 'actions-runner.zip'
+
+COPY actions-runner/.credentials /actions-runner/.credentials
+COPY actions-runner/.credentials_rsaparams /actions-runner/.credentials_rsaparams
+COPY actions-runner/.runner /actions-runner/.runner
+
+COPY ci_entrypoint.ps1 /actions-runner/ci_entrypoint.ps1
+
+ENTRYPOINT ["powershell", "-File", "ci_entrypoint.ps1"]
\ No newline at end of file
diff --git a/scripts/windows/ci_entrypoint.ps1 b/scripts/windows/ci_entrypoint.ps1
new file mode 100644
index 000000000..d68d0f5ec
--- /dev/null
+++ b/scripts/windows/ci_entrypoint.ps1
@@ -0,0 +1,5 @@
+$runnerDir = "C:\actions-runner"
+$runCmd = "$runnerDir\run.cmd"
+
+Write-Host "Starting the runner..."
+& $runCmd
\ No newline at end of file
diff --git a/scripts/windows/ci_register.ps1 b/scripts/windows/ci_register.ps1
new file mode 100644
index 000000000..a39048cdb
--- /dev/null
+++ b/scripts/windows/ci_register.ps1
@@ -0,0 +1,30 @@
+# Variables for paths and config
+$runnerDir = "C:\actions-runner"
+$configCmd = "$runnerDir\config.cmd"
+$runCmd = "$runnerDir\run.cmd"
+
+# Check required environment variables
+if (-not $env:RUNNER_TOKEN) {
+    Write-Error "RUNNER_TOKEN is not set. Exiting."
+    exit 1
+}
+if (-not $env:RUNNER_REPO_URL) {
+    Write-Error "RUNNER_REPO_URL is not set. Exiting."
+    exit 1
+}
+$env:RUNNER_NAME = "windows-amd64-cake"
+$env:RUNNER_WORKDIR = "_work"
+
+# Register the runner
+Write-Host "Registering the runner..."
+Write-Host "--url $env:RUNNER_REPO_URL"
+Write-Host "--token $env:RUNNER_TOKEN"
+Write-Host "--name $env:RUNNER_NAME"
+Write-Host "--work $env:RUNNER_WORKDIR"
+
+& $configCmd --url $env:RUNNER_REPO_URL `
+             --token $env:RUNNER_TOKEN `
+             --name $env:RUNNER_NAME `
+             --work $env:RUNNER_WORKDIR `
+             --unattended `
+             --replace
\ No newline at end of file