diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index f59ec20aa..000000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -* \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index f8cc8f9ca..9a5308e22 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -4,7 +4,7 @@ contact_links: url: https://github.com/cake-tech/cake_wallet/discussions/new?category=feature-requests about: Suggest an idea for Cake Wallet - name: Not sure where to start? - url: https://docs.cakewallet.com + url: https://guides.cakewallet.com about: Start by reading checking out the guides! - name: Need help? url: https://cakewallet.com/#contact diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 272f7bbee..18ad16e4b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -11,4 +11,3 @@ Please include a summary of the changes and which issue is fixed / feature is ad - [ ] Format code - [ ] Look for code duplication - [ ] Clear naming for variables and methods -- [ ] Manual tests in accessibility mode (TalkBack on Android) passed diff --git a/.github/workflows/automated_integration_test.yml b/.github/workflows/automated_integration_test.yml deleted file mode 100644 index 47b08c44d..000000000 --- a/.github/workflows/automated_integration_test.yml +++ /dev/null @@ -1,305 +0,0 @@ -name: Automated Integration Tests - -on: - # pull_request: - # branches: [main, CW-659-Transaction-History-Automated-Tests] - workflow_dispatch: - inputs: - branch: - description: "Branch name to build" - required: true - default: "main" - -jobs: - Automated_integration_test: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - api-level: [29] - # arch: [x86, x86_64] - 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 - 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.27.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: 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 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 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: Generate key properties - run: | - cd /opt/android/cake_wallet - flutter packages pub 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 - flutter packages pub run tool/generate_localization.dart - - - name: Build generated code - run: | - cd /opt/android/cake_wallet - ./model_generator.sh - - - 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 - echo "const changeNowCakeWalletApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart - echo "const changeNowMoneroApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart - echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart - echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart - echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart - echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart - echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart - 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 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 - echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart - echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart - echo "const trocadorMoneroApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart - echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart - echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart - 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 chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart - echo "const exolixCakeWalletApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart - echo "const exolixMoneroApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart - echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart - echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart - 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 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 - echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart - echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart - echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart - echo "const swapTradeExchangeMarkup = '${{ secrets.SWAPTRADE_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart - echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart - echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart - 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.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 - 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 - # end of test secrets - echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart - echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart - echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.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 - - - name: Build - run: | - cd /opt/android/cake_wallet - flutter build apk --release --split-per-abi - - # - name: Rename apk file - # run: | - # cd /opt/android/cake_wallet/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 - - # - name: Upload Artifact - # uses: kittaakos/upload-artifact-as-is@v0 - # with: - # path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/ - - # - 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/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk - # channel: ${{ secrets.SLACK_APK_CHANNEL }} - # title: "${{ env.BRANCH_NAME }}.apk" - # filename: ${{ env.BRANCH_NAME }}.apk - # initial_comment: ${{ github.event.head_commit.message }} - - - name: 🦾 Enable KVM - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - - name: 🦾 Cache gradle - uses: gradle/actions/setup-gradle@v3 - - - name: 🦾 Cache AVD - uses: actions/cache@v4 - id: avd-cache - with: - path: | - ~/.android/avd/* - ~/.android/adb* - key: avd-${{ matrix.api-level }} - - - name: 🦾 Create AVD and generate snapshot for caching - if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: ${{ matrix.api-level }} - force-avd-creation: false - # arch: ${{ matrix.arch }} - emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - working-directory: /opt/android/cake_wallet - disable-animations: false - script: echo "Generated AVD snapshot for caching." - - - name: 🚀 Integration tests on Android Emulator - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: ${{ matrix.api-level }} - force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: true - working-directory: /opt/android/cake_wallet - script: | - chmod a+rx integration_test_runner.sh - ./integration_test_runner.sh diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml new file mode 100644 index 000000000..938027e81 --- /dev/null +++ b/.github/workflows/cache_dependencies.yml @@ -0,0 +1,83 @@ +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.jks + key: $STORE_PASS + + - 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/no_http_imports.yaml b/.github/workflows/no_http_imports.yaml deleted file mode 100644 index dad6821ac..000000000 --- a/.github/workflows/no_http_imports.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: No http imports - -on: [pull_request] - -jobs: - PR_test_build: - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - - name: Check for http package usage - if: github.event_name == 'pull_request' - run: | - GIT_GREP_OUT="$(git grep package:http | (grep .dart: || test $? = 1) | (grep -v proxy_wrapper.dart || test $? = 1) | (grep -v very_insecure_http_do_not_use || test $? = 1) || true)" - [[ "x$GIT_GREP_OUT" == "x" ]] && exit 0 - echo "$GIT_GREP_OUT" - echo "There are .dart files which use http imports" - echo "Using http package breaks proxy integration" - echo "Please use ProxyWrapper.getHttpClient() from package:cw_core/utils/proxy_wrapper.dart" - exit 1 - \ No newline at end of file diff --git a/.github/workflows/no_print_in_dart.yaml b/.github/workflows/no_print_in_dart.yaml deleted file mode 100644 index 507793bd8..000000000 --- a/.github/workflows/no_print_in_dart.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: No print statements in dart files - -on: [pull_request] - -jobs: - PR_test_build: - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - - name: Check for print() statements in dart code (use printV() instead) - if: github.event_name == 'pull_request' - run: | - GIT_GREP_OUT="$(git grep ' print(' | (grep .dart: || test $? = 1) | (grep -v print_verbose.dart || test $? = 1) | (grep -v print_verbose_dummy.dart || test $? = 1) || true)" - [[ "x$GIT_GREP_OUT" == "x" ]] && exit 0 - echo "$GIT_GREP_OUT" - echo "There are .dart files which use print() statements" - echo "Please use printV from package:cw_core/utils/print_verbose.dart" - exit 1 diff --git a/.github/workflows/no_restricted_imports.yaml b/.github/workflows/no_restricted_imports.yaml deleted file mode 100644 index 03c3de018..000000000 --- a/.github/workflows/no_restricted_imports.yaml +++ /dev/null @@ -1,47 +0,0 @@ -name: No restricted imports in lib directory - -on: [pull_request] - -jobs: - check_restricted_imports: - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - - name: Check for restricted imports in lib directory - if: github.event_name == 'pull_request' - run: | - RESTRICTED_PACKAGES=( - "cw_bitcoin" - "cw_bitcoin_cash" - "cw_ethereum" - "cw_evm" - "cw_haven" - "cw_mweb" - "cw_nano" - "cw_polygon" - "cw_solana" - "cw_tron" - "cw_wownero" - "cw_zano" - ) - - FOUND_RESTRICTED=false - - for package in "${RESTRICTED_PACKAGES[@]}"; do - GREP_RESULT=$(find lib -type f -name "*.dart" -exec grep -l "import.*package:$package" {} \; || true) - - if [ -n "$GREP_RESULT" ]; then - echo "Found restricted import of '$package' in the following files:" - echo "$GREP_RESULT" - FOUND_RESTRICTED=true - fi - done - - if [ "$FOUND_RESTRICTED" = true ]; then - echo "Error: Restricted package imports found in lib/ directory" - echo "Please remove these imports as they are not allowed in the lib/ directory" - exit 1 - else - echo "No restricted imports found. All good!" - fi \ No newline at end of file diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index f7c226ce4..9df11f7ab 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -1,105 +1,166 @@ -name: Cake Wallet Android +name: PR Test Build -on: [pull_request] +on: + pull_request: + branches: [main] + workflow_dispatch: + inputs: + branch: + description: "Branch name to build" + required: true + default: "main" -defaults: - run: - shell: bash jobs: PR_test_build: - runs-on: linux-amd64 - container: - image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly - 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 + runs-on: ubuntu-20.04 strategy: matrix: api-level: [29] + env: + STORE_PASS: test@cake_wallet + KEY_PASS: test@cake_wallet + PR_NUMBER: ${{ github.event.number }} steps: - - name: Fix github actions messing up $HOME... - run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV' - - uses: actions/checkout@v4 + - 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: - ref: ${{ github.event.pull_request.head.sha }} - - name: configure git + 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 --add safe.directory '*' - git config --global user.email "ci@cakewallet.com" - git config --global user.name "CakeWallet CI" - - name: Get the full commit message + 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: | - FULL_MESSAGE="$(git log -1 --pretty=%B)" - echo "message<> $GITHUB_ENV - echo "$FULL_MESSAGE" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV + sudo apt update + 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 ${{ env.BRANCH_NAME }} + 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: Cache Keystore +# id: cache-keystore +# uses: actions/cache@v3 +# with: +# path: /opt/android/cake_wallet/android/app/key.jks +# key: $STORE_PASS +# +# - 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: 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 - 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 - 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 changeNowCakeWalletApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart - echo "const changeNowMoneroApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> 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 + 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 echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart @@ -113,205 +174,118 @@ jobs: echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart - echo "const trocadorMoneroApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart + echo "const payfuraApiKey = '${{ secrets.PAYFURA_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 exolixCakeWalletApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart - echo "const exolixMoneroApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> 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 echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart 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 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 echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart - echo "const swapTradeExchangeMarkup = '${{ secrets.SWAPTRADE_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart + echo "const quantexExchangeMarkup = '${{ secrets.QUANTEX_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart 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.dart + echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar 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 - # 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 - # end of test secrets - echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart - echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart - echo "const kryptonimApiKey = '${{ secrets.KRYPTONIM_API_KEY }}';" >> lib/.secrets.g.dart - echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> 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 Decred - run: | - set -x -e - pushd scripts/android - ./build_decred.sh - popd - - - name: Build generated code - run: | - flutter --version - flutter clean - rm -rf .dart_tool - rm pubspec.lock - flutter pub get - ./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: | - 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 + echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties - echo -e "id=com.cakewallet.test_${sanitized_branch_name}\nname=${BRANCH_NAME}" > android/app.properties + # 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 - name: Build run: | - flutter build apk --dart-define=hasDevOptions=true --release --split-per-abi + 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 build/app/outputs/flutter-apk + cd /opt/android/cake_wallet/build/app/outputs/flutter-apk mkdir test-apk - cp app-arm64-v8a-release.apk test-apk/${BRANCH_NAME}.apk - cp app-x86_64-release.apk test-apk/${BRANCH_NAME}_x86.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 - - name: Find APK file - id: find_apk - run: | - set -x - apk_file=$(ls build/app/outputs/flutter-apk/test-apk/${BRANCH_NAME}.apk || exit 1) - echo "APK_FILE=$apk_file" >> $GITHUB_ENV + - name: Upload Artifact + uses: kittaakos/upload-artifact-as-is@v0 + with: + path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/ - - name: Upload artifact to slack - if: ${{ !contains(env.message, 'skip slack') }} + # 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 continue-on-error: true uses: adrey/slack-file-upload-action@1.0.5 with: token: ${{ secrets.SLACK_APP_TOKEN }} - path: ${{ env.APK_FILE }} + path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk channel: ${{ secrets.SLACK_APK_CHANNEL }} - initial_comment: ${{ env.message }} + 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" diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml index f057b19e5..9e25f9f7a 100644 --- a/.github/workflows/pr_test_build_linux.yml +++ b/.github/workflows/pr_test_build_linux.yml @@ -1,98 +1,141 @@ -name: Cake Wallet Linux +name: PR Test Build linux -on: [pull_request] +on: + pull_request: + branches: [main] + workflow_dispatch: + inputs: + branch: + description: "Branch name to build" + required: true + default: "main" -defaults: - run: - shell: bash jobs: PR_test_build: - runs-on: linux-amd64 - container: - image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly - 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 + runs-on: ubuntu-20.04 + env: + STORE_PASS: test@cake_wallet + KEY_PASS: test@cake_wallet + PR_NUMBER: ${{ github.event.number }} steps: - - name: Fix github actions messing up $HOME... - run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV' - - uses: actions/checkout@v4 + - 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: - ref: ${{ github.event.pull_request.head.sha }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: configure git + java-version: "17.x" + - name: Configure placeholder git details run: | - git config --global --add safe.directory '*' - git config --global user.email "ci@cakewallet.com" - git config --global user.name "CakeWallet CI" - - name: Get the full commit message + 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: | - FULL_MESSAGE="$(git log -1 --pretty=%B)" - echo "message<> $GITHUB_ENV - echo "$FULL_MESSAGE" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV + 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 + - 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 - 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 changeNowCakeWalletApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart - echo "const changeNowMoneroApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> 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 + 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 echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart @@ -101,217 +144,71 @@ 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 echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart - echo "const trocadorMoneroApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart + echo "const payfuraApiKey = '${{ secrets.PAYFURA_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 exolixCakeWalletApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart - echo "const exolixMoneroApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> 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 echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart 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 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 echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart - echo "const swapTradeExchangeMarkup = '${{ secrets.SWAPTRADE_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart + echo "const quantexExchangeMarkup = '${{ secrets.QUANTEX_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart 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.dart + echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar 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 - # 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 - # end of test secrets - echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart - echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart - echo "const kryptonimApiKey = '${{ secrets.KRYPTONIM_API_KEY }}';" >> lib/.secrets.g.dart - echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.dart - - name: prepare monero_c and cache + - name: Rename app 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 + echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties - 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 + - name: Build run: | - pushd scripts/linux - source ./app_env.sh cakewallet - ./app_config.sh - popd + cd /opt/android/cake_wallet + flutter build linux --release - - name: Build monero_c + - name: Prepare release zip file run: | - pushd scripts/linux/ - source ./app_env.sh cakewallet - ./build_monero_all.sh - popd + cd /opt/android/cake_wallet/build/linux/x64/release + zip -r ${{env.BRANCH_NAME}}.zip bundle - - 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: | - flutter build linux --dart-define=hasDevOptions=true --release - - - name: Compress release - run: | - pushd build/linux/x64/release - zip -r cakewallet_linux.zip bundle - popd - - - name: Upload Artifact to github - uses: actions/upload-artifact@v4 + - name: Upload Artifact + uses: kittaakos/upload-artifact-as-is@v0 with: - path: ${{ github.workspace }}/build/linux/x64/release/cakewallet_linux.zip - name: cakewallet_linux + path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip - - name: Prepare virtual desktop - if: ${{ contains(env.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(env.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(env.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(env.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(env.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: Test [cw_monero] - timeout-minutes: 2 - run: cd cw_monero && flutter test - - 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 +# 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 }} diff --git a/.gitignore b/.gitignore index 84a7ecdcd..970241189 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ .history .svn/ .fvm/ -.fvmrc # IntelliJ related *.iml @@ -127,7 +126,7 @@ cw_shared_external/ios/External/ cw_haven/ios/External/ cw_haven/android/.externalNativeBuild/ cw_haven/android/.cxx/ -cw_zano/ios/External/ + lib/bitcoin/bitcoin.dart lib/monero/monero.dart lib/haven/haven.dart @@ -138,31 +137,10 @@ lib/polygon/polygon.dart lib/solana/solana.dart lib/tron/tron.dart lib/wownero/wownero.dart -lib/zano/zano.dart -lib/decred/decred.dart - -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png -ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png +ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png +ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png +ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png ios/Runner/Info.plist android/app/src/main/res/mipmap-* android/app/src/main/res/drawable/ic_launcher.png @@ -192,7 +170,6 @@ macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png macos/Runner/Configs/AppInfo.xcconfig -macos/Runner.xcodeproj/project.pbxproj integration_test/playground.dart @@ -202,28 +179,3 @@ scripts/monero_c # iOS generated framework bin ios/MoneroWallet.framework/MoneroWallet ios/WowneroWallet.framework/WowneroWallet -ios/ZanoWallet.framework/ZanoWallet -*_libwallet2_api_c.dylib - -.flatpak-builder -cake_wallet.flatpak -flatpak-build/ - -# macOS -**/Flutter/ephemeral/ -**/Pods/ -**/macos/Flutter/GeneratedPluginRegistrant.swift -**/macos/Flutter/ephemeral -**/xcuserdata/ - -# Windows -**/windows/flutter/ephemeral/ -**/windows/flutter/generated_plugin_registrant.cc -**/windows/flutter/generated_plugin_registrant.h -**/windows/flutter/generated_plugins.cmake - -# Linux -**/linux/flutter/ephemeral/ -**/linux/flutter/generated_plugin_registrant.cc -**/linux/flutter/generated_plugin_registrant.h -**/linux/flutter/generated_plugins.cmake diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 151b7af20..000000000 --- a/Dockerfile +++ /dev/null @@ -1,190 +0,0 @@ -# docker buildx build --push --pull --platform linux/amd64,linux/arm64 . -f Dockerfile -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly - -# 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 - -FROM docker.io/debian:12 - -LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet - -# Set necessary environment variables -# Set Go version to latest known-working version -ENV GOLANG_VERSION=1.24.1 - -# Pin Flutter version to latest known-working version -ENV FLUTTER_VERSION=3.27.0 - -# Pin Android Studio, platform, and build tools versions to latest known-working version -# Comes from https://developer.android.com/studio/#command-tools -ENV ANDROID_SDK_TOOLS_VERSION=13114758 -# Comes from https://developer.android.com/studio/releases/build-tools -ENV ANDROID_PLATFORM_VERSION=35 -ENV ANDROID_BUILD_TOOLS_VERSION=34.0.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 -ENV ANDROID_HOME=/opt/android-sdk-linux \ - LANG=en_US.UTF-8 \ - LC_ALL=en_US.UTF-8 \ - LANGUAGE=en_US:en - -# Set Android SDK paths -ENV ANDROID_SDK_ROOT=$ANDROID_HOME \ - PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator - -# Upgrade base image -RUN apt-get update \ - && apt-get upgrade -y - -# Install all build dependencies -RUN set -o xtrace \ - && cd /opt \ - && apt-get install -y --no-install-recommends --no-install-suggests \ - # Core dependencies - bc build-essential curl default-jdk git jq lcov libglu1-mesa libpulse0 libsqlite3-dev libstdc++6 locales openssh-client ruby-bundler ruby-full software-properties-common sudo unzip wget zip \ - # for x86 emulators - libatk-bridge2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libnss3-dev libsqlite3-dev libxtst6 libxss1 lftp sqlite3 xxd \ - # Linux desktop dependencies - clang cmake libgtk-3-dev ninja-build pkg-config \ - # monero_c dependencies - autoconf automake build-essential ccache gperf libtool llvm \ - # extra stuff for KVM - bridge-utils libvirt-clients libvirt-daemon-system qemu-kvm udev \ - # Linux test dependencies - ffmpeg network-manager x11-utils xvfb psmisc \ - # aarch64-linux-gnu dependencies - g++-aarch64-linux-gnu gcc-aarch64-linux-gnu \ - # x86_64-linux-gnu dependencies - g++-x86-64-linux-gnu gcc-x86-64-linux-gnu \ - # flatpak dependencies - flatpak flatpak-builder binutils elfutils patch unzip xz-utils zstd \ - && apt clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ - && sh -c 'echo "en_US.UTF-8 UTF-8" > /etc/locale.gen' \ - && locale-gen \ - && update-locale LANG=en_US.UTF-8 - -ENV FLATPAK_RUNTIME_VERSION=24.08 -RUN flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo \ - && flatpak install -y flathub org.freedesktop.Platform//${FLATPAK_RUNTIME_VERSION} \ - && flatpak install -y flathub org.freedesktop.Sdk//${FLATPAK_RUNTIME_VERSION} - -# Install nodejs for Github Actions -RUN curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \ - apt-get install -y --no-install-recommends nodejs && \ - apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -# Install Go -ENV PATH=${PATH}:/usr/local/go/bin:${HOME}/go/bin -ENV GOROOT=/usr/local/go -ENV GOPATH=${HOME}/go -RUN ARCH=$(uname -m) && \ - if [ "$ARCH" = "x86_64" ]; then \ - wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz -O go.tar.gz; \ - elif [ "$ARCH" = "aarch64" ]; then \ - wget https://go.dev/dl/go${GOLANG_VERSION}.linux-arm64.tar.gz -O go.tar.gz; \ - else \ - echo "Unsupported architecture: $ARCH"; exit 1; \ - fi && \ - rm -rf /usr/local/go && \ - tar -C /usr/local -xzf go.tar.gz && \ - rm go.tar.gz && \ - go install golang.org/x/mobile/cmd/gomobile@latest && \ - gomobile init - -RUN git config --global user.email "czarek@cakewallet.com" \ - && git config --global user.name "CakeWallet CI" - - -# Install Android SDK commandline tools and emulator -RUN ARCH=$(uname -m) && \ - if [ "$ARCH" != "x86_64" ]; then exit 0; fi \ - && 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 \ - - -# Handle emulator not being available on linux/arm64 (https://issuetracker.google.com/issues/227219818) -RUN ARCH=$(uname -m) && \ - if [ "$ARCH" != "x86_64" ]; then exit 0; fi \ - && sdkmanager emulator - -# Pre-install extra Android SDK dependencies in order to not have to download them for each build -RUN ARCH=$(uname -m) && \ - if [ "$ARCH" != "x86_64" ]; then exit 0; fi \ - && yes | sdkmanager \ - "platforms;android-$ANDROID_PLATFORM_VERSION" \ - "build-tools;$ANDROID_BUILD_TOOLS_VERSION" \ - "platforms;android-33" \ - "platforms;android-34" \ - "platforms;android-35" \ - "build-tools;33.0.2" \ - "build-tools;33.0.1" \ - "build-tools;33.0.0" \ - "build-tools;35.0.0" - -# Install extra NDK dependency for sp_scanner -ENV ANDROID_NDK_VERSION=27.2.12479018 -RUN ARCH=$(uname -m) && \ - if [ "$ARCH" != "x86_64" ]; then exit 0; fi \ - && yes | sdkmanager "ndk;$ANDROID_NDK_VERSION" \ - "ndk;27.0.12077973" - -# Install dependencies for tests -# Comes from https://github.com/ReactiveCircus/android-emulator-runner -RUN ARCH=$(uname -m) && \ - if [ "$ARCH" != "x86_64" ]; then exit 0; fi \ - && yes | sdkmanager \ - "system-images;android-29;default;x86_64" \ - "system-images;android-31;default;x86_64" \ - "platforms;android-29" \ - "platforms;android-31" - -# Fake the KVM status so the 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 - -# Install rustup, rust toolchains, and cargo-ndk -ENV PATH=${HOME}/.cargo/bin:${PATH} -RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \ - cargo install cargo-ndk && \ - for toolchain in stable nightly; \ - do \ - for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu; \ - do \ - rustup target add --toolchain $toolchain $target; \ - done \ - done - -# Download and install Flutter -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 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} && \ - cd ${FLUTTER_HOME} && \ - git fetch -a - -RUN yes | flutter doctor --android-licenses \ - && flutter doctor \ - && chown -R root:root ${FLUTTER_HOME} - -# Download and pre-cache necessary Flutter artifacts to speed up builds -RUN flutter precache diff --git a/LICENSE.md b/LICENSE.md index 09bb6208b..4268b9710 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2025 Cake Labs LLC +Copyright (c) 2018-2023 Cake Labs LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ea796dbf2..078c4437e 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,10 @@ Cake Wallet includes support for several cryptocurrencies, including: * Ethereum (ETH) * Litecoin (LTC) * Bitcoin Cash (BCH) -* Polygon (POL) +* Polygon (Pol) * Solana (SOL) -* Tron (TRX) * Nano (XNO) -* Zano (ZANO) -* Decred (DCR) -* Wownero (WOW) +* Haven (XHV) ## Features @@ -84,6 +81,10 @@ Cake Wallet includes support for several cryptocurrencies, including: * Automatically generate new addresses * Specify multiple recipients for batch sending +### Haven Specific Features + +* Send, receive, and store XHV and all xAssets like xUSD, xEUR, xAG, etc. + # Monero.com by Cake Wallet for Android and iOS ## Open Source Monero-Only Wallet @@ -98,17 +99,6 @@ Cake Wallet includes support for several cryptocurrencies, including: * F-Droid: https://fdroid.cakelabs.com * APK: https://github.com/cake-tech/cake_wallet/releases -### APK Verification - -APK releases on GitHub, Accrescent, and F-Droid use the same key. They can easily be verified using [apksigner](https://developer.android.com/tools/apksigner#options-verify) or [AppVerifier](https://github.com/soupslurpr/AppVerifier). - -See below for Cake Wallet's SHA-256 signing certificate hash: - -``` -com.cakewallet.cake_wallet -C5:40:53:AB:0F:10:D9:54:17:62:A3:DA:76:65:AE:3D:BA:5E:7C:74:3A:B4:F1:08:A5:34:9D:62:AC:10:6E:F5 -``` - # Support We have 24/7 free support. Please contact support@cakewallet.com diff --git a/docs/SECURITY.md b/SECURITY.md similarity index 100% rename from docs/SECURITY.md rename to SECURITY.md diff --git a/analysis_options.yaml b/analysis_options.yaml index bd35233ba..be68a4f26 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -22,7 +22,6 @@ analyzer: lib/solana/cw_solana.dart, lib/tron/cw_tron.dart, lib/wownero/cw_wownero.dart, - lib/zano/cw_zano.dart, ] language: strict-casts: true diff --git a/android/app/build.gradle b/android/app/build.gradle index 4a8045bb3..c19211117 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,9 +1,3 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -12,6 +6,11 @@ if (localPropertiesFile.exists()) { } } +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -22,6 +21,9 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { @@ -35,22 +37,14 @@ if (appPropertiesFile.exists()) { } android { - compileSdkVersion 35 - buildToolsVersion "35.0.0" + compileSdkVersion 34 + buildToolsVersion "34.0.0" lintOptions { disable 'InvalidPackage' } - compileOptions { - coreLibraryDesugaringEnabled true - - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - - namespace "com.cakewallet.cake_wallet" + namespace appProperties['id'] defaultConfig { applicationId appProperties['id'] @@ -81,11 +75,12 @@ android { buildTypes { release { signingConfig signingConfigs.release + + shrinkResources false + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } - debug { - signingConfig signingConfigs.release - } } ndkVersion "27.0.12077973" @@ -99,10 +94,9 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' } configurations { implementation.exclude module:'proto-google-common-protos' implementation.exclude module:'protolite-well-known-types' implementation.exclude module:'protobuf-javalite' -} +} \ No newline at end of file diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index a733bae9e..d24d7f10a 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -5,98 +5,4 @@ -keep class io.flutter.view.** { *; } -keep class io.flutter.** { *; } -keep class io.flutter.plugins.** { *; } --dontwarn io.flutter.embedding.** --dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication - -# start reown --dontwarn com.github.luben.zstd.BufferPool --dontwarn com.github.luben.zstd.ZstdInputStream --dontwarn com.github.luben.zstd.ZstdOutputStream --dontwarn com.google.api.client.http.GenericUrl --dontwarn com.google.api.client.http.HttpHeaders --dontwarn com.google.api.client.http.HttpRequest --dontwarn com.google.api.client.http.HttpRequestFactory --dontwarn com.google.api.client.http.HttpResponse --dontwarn com.google.api.client.http.HttpTransport --dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder --dontwarn com.google.api.client.http.javanet.NetHttpTransport --dontwarn java.awt.Color --dontwarn java.awt.Dimension --dontwarn java.awt.Graphics2D --dontwarn java.awt.Graphics --dontwarn java.awt.Image --dontwarn java.awt.Point --dontwarn java.awt.Polygon --dontwarn java.awt.Shape --dontwarn java.awt.color.ColorSpace --dontwarn java.awt.geom.AffineTransform --dontwarn java.awt.image.BufferedImage --dontwarn java.awt.image.ColorModel --dontwarn java.awt.image.ComponentColorModel --dontwarn java.awt.image.ComponentSampleModel --dontwarn java.awt.image.DataBuffer --dontwarn java.awt.image.DataBufferByte --dontwarn java.awt.image.DataBufferInt --dontwarn java.awt.image.DataBufferUShort --dontwarn java.awt.image.ImageObserver --dontwarn java.awt.image.MultiPixelPackedSampleModel --dontwarn java.awt.image.Raster --dontwarn java.awt.image.RenderedImage --dontwarn java.awt.image.SampleModel --dontwarn java.awt.image.SinglePixelPackedSampleModel --dontwarn java.awt.image.WritableRaster --dontwarn java.beans.BeanInfo --dontwarn java.beans.FeatureDescriptor --dontwarn java.beans.IntrospectionException --dontwarn java.beans.Introspector --dontwarn java.beans.PropertyDescriptor --dontwarn java.lang.reflect.InaccessibleObjectException --dontwarn javax.imageio.IIOImage --dontwarn javax.imageio.ImageIO --dontwarn javax.imageio.ImageWriteParam --dontwarn javax.imageio.ImageWriter --dontwarn javax.imageio.metadata.IIOMetadata --dontwarn javax.imageio.stream.ImageOutputStream --dontwarn javax.swing.JComponent --dontwarn javax.swing.JFileChooser --dontwarn javax.swing.JFrame --dontwarn javax.swing.JPanel --dontwarn javax.swing.ProgressMonitor --dontwarn javax.swing.SwingUtilities --dontwarn org.brotli.dec.BrotliInputStream --dontwarn org.joda.time.Instant --dontwarn org.objectweb.asm.AnnotationVisitor --dontwarn org.objectweb.asm.Attribute --dontwarn org.objectweb.asm.ClassReader --dontwarn org.objectweb.asm.ClassVisitor --dontwarn org.objectweb.asm.FieldVisitor --dontwarn org.objectweb.asm.Label --dontwarn org.objectweb.asm.MethodVisitor --dontwarn org.objectweb.asm.Type --dontwarn org.tukaani.xz.ARMOptions --dontwarn org.tukaani.xz.ARMThumbOptions --dontwarn org.tukaani.xz.DeltaOptions --dontwarn org.tukaani.xz.FilterOptions --dontwarn org.tukaani.xz.FinishableOutputStream --dontwarn org.tukaani.xz.FinishableWrapperOutputStream --dontwarn org.tukaani.xz.IA64Options --dontwarn org.tukaani.xz.LZMA2InputStream --dontwarn org.tukaani.xz.LZMA2Options --dontwarn org.tukaani.xz.LZMAInputStream --dontwarn org.tukaani.xz.LZMAOutputStream --dontwarn org.tukaani.xz.MemoryLimitException --dontwarn org.tukaani.xz.PowerPCOptions --dontwarn org.tukaani.xz.SPARCOptions --dontwarn org.tukaani.xz.SingleXZInputStream --dontwarn org.tukaani.xz.UnsupportedOptionsException --dontwarn org.tukaani.xz.X86Options --dontwarn org.tukaani.xz.XZ --dontwarn org.tukaani.xz.XZInputStream --dontwarn org.tukaani.xz.XZOutputStream --dontwarn us.hebi.matlab.mat.ejml.Mat5Ejml --dontwarn us.hebi.matlab.mat.format.Mat5 --dontwarn us.hebi.matlab.mat.format.Mat5File --dontwarn us.hebi.matlab.mat.types.Array --dontwarn us.hebi.matlab.mat.types.MatFile$Entry --dontwarn us.hebi.matlab.mat.types.MatFile -# end reown \ No newline at end of file +-dontwarn io.flutter.embedding.** \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index f880684a6..dc767a55d 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,4 +1,5 @@ - + diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 8283a7c8c..5b080e3ec 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -1,4 +1,5 @@ - + @@ -24,10 +25,6 @@ - - - - - - - - - - - @@ -111,15 +98,10 @@ - - - + diff --git a/android/build.gradle b/android/build.gradle index d42aa24b4..66de0bdca 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,8 +1,21 @@ +buildscript { + ext.kotlin_version = '2.0.21' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.7.1' + classpath 'com.google.gms:google-services:4.3.8' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + allprojects { repositories { google() mavenCentral() - maven { url "https://jitpack.io" } } } diff --git a/android/settings.gradle b/android/settings.gradle index 468f9b55f..5a2f14fb1 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,26 +1,15 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() +include ':app' - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - repositories { - google() - mavenCentral() - gradlePluginPortal() - } +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } } -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.7.1" apply false - id "org.jetbrains.kotlin.android" version "2.0.21" apply false - id "com.google.gms.google-services" version "4.3.8" apply false +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory } - -include ":app" \ No newline at end of file diff --git a/assets/decred_node_list.yml b/assets/decred_node_list.yml deleted file mode 100644 index cb171e701..000000000 --- a/assets/decred_node_list.yml +++ /dev/null @@ -1,6 +0,0 @@ -- - uri: default-spv-nodes - is_default: true -- - uri: dcrd.sethforprivacy.com:9108 - useSSL: true \ No newline at end of file diff --git a/assets/ethereum_server_list.yml b/assets/ethereum_server_list.yml index ed425c3c7..125085d88 100644 --- a/assets/ethereum_server_list.yml +++ b/assets/ethereum_server_list.yml @@ -1,14 +1,10 @@ - - uri: ethereum-rpc.publicnode.com - useSSL: true - isDefault: true + uri: ethereum.publicnode.com - uri: eth.llamarpc.com - uri: rpc.flashbots.net - uri: eth-mainnet.public.blastapi.io -- - uri: eth.nownodes.io - uri: ethereum.publicnode.com \ No newline at end of file diff --git a/assets/faq/faq_pl.json b/assets/faq/faq_pl.json index b41841cd8..a38d79068 100644 --- a/assets/faq/faq_pl.json +++ b/assets/faq/faq_pl.json @@ -13,7 +13,7 @@ }, { "question" : "Co oznaczają słowa „seed” i „keys”?", - "answer" : "Twoje klucze i fraza seed zawierają prywatne informacje o twoim portfelu i pozwalają wysyłać kryptowalutę oraz zobaczyć przychodzące transakcje.\nFraza „seed” to wersja twojego klucza prywatnego napisana w sposób, który łatwiej Ci zapisać. Wasze frazy seed i klucze są w rzeczywistości takie same, tylko w różnych formach zapisu!\nNigdy nie dawaj nikomu swojej frazy seed ani swoich kluczy. Twoje fundusze zostaną skradzione, jeśli upublicznisz frazę seed lub klucze. Zapisz jednak swoją frazę seed i przechowuj ją w bezpiecznym miejscu (pozwoli to przywrócić portfel, jeśli zgubisz telefon).\n" + "answer" : "Twoje klucze kodują prywatne informacje w twoim portfelu i pozwalają wydać monety i zobaczyć przychodzące transakcje.\nTwoje ziarno to tylko wersja twojego klucza prywatnego napisana w sposób, który łatwiej Ci zapisać. Wasze nasiona i klucze są w rzeczywistości takie same, tylko w różnych formach!\nNigdy nie dawaj nikomu swojego ziarna ani kluczy. Twoje fundusze zostaną skradzione, jeśli wydasz swoje nasiona lub klucze. Zapisz jednak swoje ziarno i przechowuj je w bezpiecznym miejscu (pozwoli to przywrócić portfel, jeśli zgubisz telefon).\n" }, { "question" : "Ile portfeli mogę utworzyć?", @@ -24,11 +24,11 @@ "answer" : "Stuknij menu •••, wybierz „Portfele”, a następnie „Przywróć portfel”. Następnie wprowadź dane początkowe (lub klucze) i opcjonalnie wprowadź datę przed pierwszą transakcją w portfelu (przyspieszy to proces synchronizacji .) Może być konieczne pozostawienie aplikacji otwartej przez 15-30 minut, aby całkowicie przywrócić portfel.\n" }, { - "question" : "Co mogę zrobić, jeśli zapomniałem frazę seed?", - "answer" : "Jeśli zapomniałeś swoją frazę seed, prawdopodobnie gdzieś je zapisałeś. Sprawdź swoje notatki i rozejrzyj się po komputerze. Jeśli nie możesz go nigdzie znaleźć, być może utworzono kopię zapasową Cake Wallet (w takim przypadku będziesz mógł przywrócić dane z tej kopii zapasowej). Jeśli żadna z tych czynności nie działa, niestety nic nie możemy zrobić.\n" + "question" : "Co mogę zrobić, jeśli stracę nasiona?", + "answer" : "Jeśli zapomniałeś o nasieniu, prawdopodobnie gdzieś je zapisałeś. Sprawdź swoje notatki i rozejrzyj się po komputerze. Jeśli nie możesz go nigdzie znaleźć, być może utworzono kopię zapasową Cake Wallet (w takim przypadku będziesz mógł przywrócić dane z tej kopii zapasowej). Jeśli żadna z tych czynności nie działa, niestety nic nie możemy zrobić.\n" }, { - "question" : "Czy zbieracie jakieś informacje o moim portfelu?", + "question" : "Czy zbierasz jakieś informacje o moim portfelu?", "answer" : "Portfel Cake NIE gromadzi ani nie rejestruje żadnych informacji o Twoim portfelu. Dbamy o Twoją prywatność.\n" }, { @@ -37,7 +37,7 @@ }, { "question" : "Co to są „podadresy” i jak z nich korzystać?", - "answer" : "Podadres jest w unikalnym adresem, który można wygenerować w dowolnym momencie. Monety wysłane do niego nadal będą pojawiać się w głównym portfelu, ale osoba wysyłająca monety nie zna Twojego głównego adresu. Podadresy zawsze zaczynają się od „8”.\nMożesz utworzyć nowy podadres na ekranie Odbieranie, dotykając „+” obok przycisku Podadresy. Wprowadź nazwę podadresu i dotknij „Dodaj”. Następnie dotknij nazwy podadresu, gdy chcesz go użyć!\nJeśli jesteś paranoikiem, prawdopodobnie za każdym razem, gdy otrzymasz Monero, powinieneś utworzyć nowy podadres.\n" + "answer" : "Podadres jest w zasadzie unikalnym adresem, który można wygenerować w dowolnym momencie. Monety wysłane do niego nadal będą pojawiać się w głównym portfelu, ale osoba wysyłająca monety nie może podać Twojego głównego adresu. Podadresy zawsze zaczynają się od „8”.\nMożesz utworzyć nowy podadres na ekranie Odbieranie, dotykając „+” obok przycisku Podadresy. Wprowadź nazwę podadresu i dotknij „Dodaj”. Następnie dotknij nazwy podadresu, gdy chcesz go użyć!\nJeśli jesteś paranoikiem, prawdopodobnie za każdym razem, gdy otrzymasz Monero, powinieneś utworzyć nowy podadres.\n" }, { "question" : "Co to jest ID transakcji?", diff --git a/assets/images/2.0x/decred.png b/assets/images/2.0x/decred.png deleted file mode 100644 index 2f4919cec..000000000 Binary files a/assets/images/2.0x/decred.png and /dev/null differ diff --git a/assets/images/2.0x/decred_menu.png b/assets/images/2.0x/decred_menu.png deleted file mode 100644 index 4a41efef1..000000000 Binary files a/assets/images/2.0x/decred_menu.png and /dev/null differ diff --git a/assets/images/2fa.png b/assets/images/2fa.png deleted file mode 100644 index 36c99beab..000000000 Binary files a/assets/images/2fa.png and /dev/null differ diff --git a/assets/images/2fa_warning_dark.svg b/assets/images/2fa_warning_dark.svg deleted file mode 100644 index c9fcad341..000000000 --- a/assets/images/2fa_warning_dark.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/2fa_warning_light.svg b/assets/images/2fa_warning_light.svg deleted file mode 100644 index 087d8e99b..000000000 --- a/assets/images/2fa_warning_light.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/3.0x/decred.png b/assets/images/3.0x/decred.png deleted file mode 100644 index b2c9ac818..000000000 Binary files a/assets/images/3.0x/decred.png and /dev/null differ diff --git a/assets/images/3.0x/decred_menu.png b/assets/images/3.0x/decred_menu.png deleted file mode 100644 index e55b3fb5c..000000000 Binary files a/assets/images/3.0x/decred_menu.png and /dev/null differ diff --git a/assets/images/birthday_cake.png b/assets/images/birthday_cake.png index 293cd10f6..84b084fba 100644 Binary files a/assets/images/birthday_cake.png and b/assets/images/birthday_cake.png differ diff --git a/assets/images/btc_lock_dark.png b/assets/images/btc_lock_dark.png deleted file mode 100644 index f5b3d7e27..000000000 Binary files a/assets/images/btc_lock_dark.png and /dev/null differ diff --git a/assets/images/btc_lock_light.png b/assets/images/btc_lock_light.png deleted file mode 100644 index 4320d96e3..000000000 Binary files a/assets/images/btc_lock_light.png and /dev/null differ diff --git a/assets/images/buy.png b/assets/images/buy.png index 32c116e6b..ff4549d5a 100644 Binary files a/assets/images/buy.png and b/assets/images/buy.png differ diff --git a/assets/images/cake_logo.png b/assets/images/cake_logo.png index abbb4e62b..8a85bf225 100644 Binary files a/assets/images/cake_logo.png and b/assets/images/cake_logo.png differ diff --git a/assets/images/cake_logo_dark.svg b/assets/images/cake_logo_dark.svg deleted file mode 100644 index 095077443..000000000 --- a/assets/images/cake_logo_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/images/cake_logo_light.svg b/assets/images/cake_logo_light.svg deleted file mode 100644 index 767e205d1..000000000 --- a/assets/images/cake_logo_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/images/cakewallet_android_icon.png b/assets/images/cakewallet_android_icon.png old mode 100644 new mode 100755 index 7f15c62f5..59cc69414 Binary files a/assets/images/cakewallet_android_icon.png and b/assets/images/cakewallet_android_icon.png differ 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 345888d26..00d924171 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 @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher.png index 89c9b0571..10d0a1a82 100644 Binary files a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher.png and b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_back.png new file mode 100644 index 000000000..5b0fde827 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_back.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 000000000..9c16f0a27 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_fore.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_background.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_background.png deleted file mode 100644 index 19669488f..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_background.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_foreground.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 1411a5da5..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_monochrome.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_monochrome.png deleted file mode 100644 index 1411a5da5..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher.png index 8f1d1c28b..8c59ec33e 100644 Binary files a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher.png and b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_back.png new file mode 100644 index 000000000..5d25e42e7 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_back.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 000000000..021fe65de Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_background.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_background.png deleted file mode 100644 index 75025cfd5..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_background.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_foreground.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index e8c47adb3..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_monochrome.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_monochrome.png deleted file mode 100644 index e8c47adb3..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher.png index f775a8fac..10c3acd7f 100644 Binary files a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher.png and b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 000000000..c4b66dc58 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 000000000..b440b154d Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_fore.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_background.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_background.png deleted file mode 100644 index 9784f16c8..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_background.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_foreground.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 6ba8eb301..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_monochrome.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_monochrome.png deleted file mode 100644 index 6ba8eb301..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher.png index 31458fa02..813a3678d 100644 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher.png and b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 000000000..75dc0219d Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 000000000..90afb19e8 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_background.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_background.png deleted file mode 100644 index 04ef206c8..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_background.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_foreground.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index cc93d633b..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_monochrome.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_monochrome.png deleted file mode 100644 index cc93d633b..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher.png index 158afbbf9..671422b96 100644 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher.png and b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 000000000..46b1e2cb1 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_back.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 000000000..0a2025220 Binary files /dev/null and b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_background.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_background.png deleted file mode 100644 index 66a5487a2..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_background.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_foreground.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 0ecd56e8c..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_monochrome.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_monochrome.png deleted file mode 100644 index 0ecd56e8c..000000000 Binary files a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/assets/images/cakewallet_app_logo.png b/assets/images/cakewallet_app_logo.png new file mode 100644 index 000000000..59cc69414 Binary files /dev/null and b/assets/images/cakewallet_app_logo.png differ diff --git a/assets/images/cakewallet_icon_1024.png b/assets/images/cakewallet_icon_1024.png index 35cf42245..64682cd1d 100644 Binary files a/assets/images/cakewallet_icon_1024.png and b/assets/images/cakewallet_icon_1024.png differ diff --git a/assets/images/cakewallet_icon_120.png b/assets/images/cakewallet_icon_120.png index 6e45f6423..1a2c1b99c 100644 Binary files a/assets/images/cakewallet_icon_120.png and b/assets/images/cakewallet_icon_120.png differ diff --git a/assets/images/cakewallet_icon_180.png b/assets/images/cakewallet_icon_180.png index da585ca42..ff69a866a 100644 Binary files a/assets/images/cakewallet_icon_180.png and b/assets/images/cakewallet_icon_180.png differ diff --git a/assets/images/cakewallet_logo.png b/assets/images/cakewallet_logo.png index c465fa26c..bf6896ad2 100644 Binary files a/assets/images/cakewallet_logo.png and b/assets/images/cakewallet_logo.png differ diff --git a/assets/images/chainflip.png b/assets/images/chainflip.png deleted file mode 100644 index e588e6361..000000000 Binary files a/assets/images/chainflip.png and /dev/null differ diff --git a/assets/images/contact.png b/assets/images/contact.png deleted file mode 100644 index 5cf96694b..000000000 Binary files a/assets/images/contact.png and /dev/null differ diff --git a/assets/images/contact_icon.svg b/assets/images/contact_icon.svg deleted file mode 100644 index 6dbfcd5f4..000000000 --- a/assets/images/contact_icon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/images/dcr_icon.png b/assets/images/dcr_icon.png index 757cd0388..609873611 100644 Binary files a/assets/images/dcr_icon.png and b/assets/images/dcr_icon.png differ diff --git a/assets/images/decred.png b/assets/images/decred.png deleted file mode 100644 index 0b12f2ef0..000000000 Binary files a/assets/images/decred.png and /dev/null differ diff --git a/assets/images/decred_icon.png b/assets/images/decred_icon.png deleted file mode 100644 index 9391abc3d..000000000 Binary files a/assets/images/decred_icon.png and /dev/null differ diff --git a/assets/images/decred_menu.png b/assets/images/decred_menu.png deleted file mode 100644 index 5c67923c5..000000000 Binary files a/assets/images/decred_menu.png and /dev/null differ diff --git a/assets/images/deuro_icon.png b/assets/images/deuro_icon.png deleted file mode 100644 index 4dc068ff8..000000000 Binary files a/assets/images/deuro_icon.png and /dev/null differ diff --git a/assets/images/discord.png b/assets/images/discord.png deleted file mode 100644 index 23fe37a36..000000000 Binary files a/assets/images/discord.png and /dev/null differ diff --git a/assets/images/discourse.png b/assets/images/discourse.png deleted file mode 100644 index b8bab2c5d..000000000 Binary files a/assets/images/discourse.png and /dev/null differ diff --git a/assets/images/flip_icon.png b/assets/images/flip_icon.png deleted file mode 100644 index e588e6361..000000000 Binary files a/assets/images/flip_icon.png and /dev/null differ diff --git a/assets/images/hero/cw_welcome_dark.svg b/assets/images/hero/cw_welcome_dark.svg deleted file mode 100644 index 5479cb1ee..000000000 --- a/assets/images/hero/cw_welcome_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/images/hero/cw_welcome_light.svg b/assets/images/hero/cw_welcome_light.svg deleted file mode 100644 index ece7d1f84..000000000 --- a/assets/images/hero/cw_welcome_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/images/history.svg b/assets/images/history.svg deleted file mode 100644 index f308ab7e3..000000000 --- a/assets/images/history.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/images/home_screen_setting_icon.svg b/assets/images/home_screen_setting_icon.svg deleted file mode 100644 index 7b3aa7b4c..000000000 --- a/assets/images/home_screen_setting_icon.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x.png deleted file mode 100644 index 3fd15f3ce..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x~ipad.png deleted file mode 100644 index 3fd15f3ce..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@3x.png deleted file mode 100644 index b6ff994f6..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20~ipad.png deleted file mode 100644 index 4be1a2317..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29.png deleted file mode 100644 index 219f2c6be..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x.png deleted file mode 100644 index ae94bb0ac..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x~ipad.png deleted file mode 100644 index ae94bb0ac..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@3x.png deleted file mode 100644 index 0ef9d3bbf..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29~ipad.png deleted file mode 100644 index 219f2c6be..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x.png deleted file mode 100644 index 9fdb32376..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x~ipad.png deleted file mode 100644 index 9fdb32376..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@3x.png deleted file mode 100644 index 485f8b37b..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40~ipad.png deleted file mode 100644 index 3fd15f3ce..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@2x~car.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@2x~car.png deleted file mode 100644 index 485f8b37b..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@2x~car.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@3x~car.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@3x~car.png deleted file mode 100644 index 50148e6dc..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@3x~car.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-83.5@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-83.5@2x~ipad.png deleted file mode 100644 index 8f290ada2..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-83.5@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x.png deleted file mode 100644 index 485f8b37b..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x~ipad.png deleted file mode 100644 index b11d7332f..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@3x.png deleted file mode 100644 index 50148e6dc..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ios-marketing.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ios-marketing.png deleted file mode 100644 index 1fce95553..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ios-marketing.png and /dev/null differ diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ipad.png deleted file mode 100644 index 7d4a82186..000000000 Binary files a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x.png deleted file mode 100644 index 7ea540caf..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x~ipad.png deleted file mode 100644 index 7ea540caf..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@3x.png deleted file mode 100644 index 6ac773754..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20~ipad.png deleted file mode 100644 index 57864a9b3..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-20~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29.png deleted file mode 100644 index 27f817dfc..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-29.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x.png deleted file mode 100644 index 0455b4409..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x~ipad.png deleted file mode 100644 index 0455b4409..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@3x.png deleted file mode 100644 index 1b8a73481..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29~ipad.png deleted file mode 100644 index 27f817dfc..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-29~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x.png deleted file mode 100644 index 963612d0c..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x~ipad.png deleted file mode 100644 index 963612d0c..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@3x.png deleted file mode 100644 index b6da404cb..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40~ipad.png deleted file mode 100644 index 7ea540caf..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-40~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-60@2x~car.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-60@2x~car.png deleted file mode 100644 index b6da404cb..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-60@2x~car.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-60@3x~car.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-60@3x~car.png deleted file mode 100644 index 37f7651a5..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-60@3x~car.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-83.5@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-83.5@2x~ipad.png deleted file mode 100644 index 21aa12463..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon-83.5@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon@2x.png deleted file mode 100644 index b6da404cb..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon@2x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon@2x~ipad.png deleted file mode 100644 index b6b63a61e..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon@2x~ipad.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon@3x.png deleted file mode 100644 index 37f7651a5..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon@3x.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon~ios-marketing.png b/assets/images/ios_icons/monero_ios_icons/AppIcon~ios-marketing.png deleted file mode 100644 index 0c977110a..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon~ios-marketing.png and /dev/null differ diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon~ipad.png deleted file mode 100644 index 849c5612a..000000000 Binary files a/assets/images/ios_icons/monero_ios_icons/AppIcon~ipad.png and /dev/null differ diff --git a/assets/images/kryptonim_dark.png b/assets/images/kryptonim_dark.png deleted file mode 100644 index 646d550ba..000000000 Binary files a/assets/images/kryptonim_dark.png and /dev/null differ diff --git a/assets/images/kryptonim_light.png b/assets/images/kryptonim_light.png deleted file mode 100644 index 85e64a3f2..000000000 Binary files a/assets/images/kryptonim_light.png and /dev/null differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png index c465fa26c..73101354a 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png index e79db4d99..9ceee3c5e 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png index 2d030845b..ef46cd805 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png index eef607c2c..6547a1b1b 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png index a09896830..e436872e8 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png index a98c5faf8..157b00493 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png differ diff --git a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png index d8141a250..a46ed4535 100644 Binary files a/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png and b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png differ diff --git a/assets/images/menu.svg b/assets/images/menu.svg deleted file mode 100644 index 0a4cc3784..000000000 --- a/assets/images/menu.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - 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 c8bd4b26c..00d924171 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,5 +2,4 @@ - \ 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 deleted file mode 100644 index af8126ea9..000000000 Binary files a/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png and /dev/null 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 deleted file mode 100644 index 0778b841f..000000000 Binary files a/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png and /dev/null 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 deleted file mode 100644 index 318914c59..000000000 Binary files a/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png and /dev/null 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 deleted file mode 100644 index b1165abe8..000000000 Binary files a/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png and /dev/null 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 deleted file mode 100644 index ea11a01d3..000000000 Binary files a/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png and /dev/null differ diff --git a/assets/images/notif.svg b/assets/images/notif.svg deleted file mode 100644 index b1ff5b4fa..000000000 --- a/assets/images/notif.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/images/notification_icon.svg b/assets/images/notification_icon.svg index 360d0b4e6..099039e67 100644 --- a/assets/images/notification_icon.svg +++ b/assets/images/notification_icon.svg @@ -1,3 +1,69 @@ - - - + + + +image/svg+xml \ No newline at end of file diff --git a/assets/images/passphrase_dark.png b/assets/images/passphrase_dark.png deleted file mode 100644 index f72d1e1a1..000000000 Binary files a/assets/images/passphrase_dark.png and /dev/null differ diff --git a/assets/images/passphrase_key.svg b/assets/images/passphrase_key.svg deleted file mode 100644 index c577dc30a..000000000 --- a/assets/images/passphrase_key.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/passphrase_light.png b/assets/images/passphrase_light.png deleted file mode 100644 index f86f68156..000000000 Binary files a/assets/images/passphrase_light.png and /dev/null differ diff --git a/assets/images/payjoin.png b/assets/images/payjoin.png deleted file mode 100644 index 1ba3dccdb..000000000 Binary files a/assets/images/payjoin.png and /dev/null differ diff --git a/assets/images/qr-cake.png b/assets/images/qr-cake.png deleted file mode 100644 index 7c54dedb0..000000000 Binary files a/assets/images/qr-cake.png and /dev/null differ diff --git a/assets/images/swap_trade.png b/assets/images/quantex.png similarity index 100% rename from assets/images/swap_trade.png rename to assets/images/quantex.png diff --git a/assets/images/receive.png b/assets/images/receive.png deleted file mode 100644 index 180a4e5b3..000000000 Binary files a/assets/images/receive.png and /dev/null differ diff --git a/assets/images/seed_verified.png b/assets/images/seed_verified.png deleted file mode 100644 index e03706193..000000000 Binary files a/assets/images/seed_verified.png and /dev/null differ diff --git a/assets/images/seed_verified_dark.png b/assets/images/seed_verified_dark.png deleted file mode 100644 index cbefa5d8c..000000000 Binary files a/assets/images/seed_verified_dark.png and /dev/null differ diff --git a/assets/images/seed_verified_light.png b/assets/images/seed_verified_light.png deleted file mode 100644 index a51eddcd7..000000000 Binary files a/assets/images/seed_verified_light.png and /dev/null differ diff --git a/assets/images/seed_warning_dark.svg b/assets/images/seed_warning_dark.svg deleted file mode 100644 index 0a47254ff..000000000 --- a/assets/images/seed_warning_dark.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/seed_warning_light.svg b/assets/images/seed_warning_light.svg deleted file mode 100644 index cab27ec31..000000000 --- a/assets/images/seed_warning_light.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/send.png b/assets/images/send.png new file mode 100644 index 000000000..aef504999 Binary files /dev/null and b/assets/images/send.png differ diff --git a/assets/images/send2.png b/assets/images/send2.png deleted file mode 100644 index 85fc570a8..000000000 Binary files a/assets/images/send2.png and /dev/null differ diff --git a/assets/images/swap.png b/assets/images/swap.png deleted file mode 100644 index fe3fc0893..000000000 Binary files a/assets/images/swap.png and /dev/null differ diff --git a/assets/images/tor_logo.svg b/assets/images/tor_logo.svg deleted file mode 100644 index ebd00324d..000000000 --- a/assets/images/tor_logo.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/usdtbsc_icon.png b/assets/images/usdtbsc_icon.png deleted file mode 100644 index 9f2cda237..000000000 Binary files a/assets/images/usdtbsc_icon.png and /dev/null differ diff --git a/assets/images/wallet_group_bright.png b/assets/images/wallet_group_bright.png new file mode 100644 index 000000000..263361db6 Binary files /dev/null and b/assets/images/wallet_group_bright.png differ diff --git a/assets/images/wallet_group_confirmed_dark.png b/assets/images/wallet_group_confirmed_dark.png deleted file mode 100644 index a047cb29c..000000000 Binary files a/assets/images/wallet_group_confirmed_dark.png and /dev/null differ diff --git a/assets/images/wallet_group_confirmed_light.png b/assets/images/wallet_group_confirmed_light.png deleted file mode 100644 index 851d32300..000000000 Binary files a/assets/images/wallet_group_confirmed_light.png and /dev/null differ diff --git a/assets/images/wallet_group_dark.png b/assets/images/wallet_group_dark.png new file mode 100644 index 000000000..7cd08d2cd Binary files /dev/null and b/assets/images/wallet_group_dark.png differ diff --git a/assets/images/wallet_group_empty_dark.png b/assets/images/wallet_group_empty_dark.png deleted file mode 100644 index e613d876e..000000000 Binary files a/assets/images/wallet_group_empty_dark.png and /dev/null differ diff --git a/assets/images/wallet_group_empty_light.png b/assets/images/wallet_group_empty_light.png deleted file mode 100644 index f795648ae..000000000 Binary files a/assets/images/wallet_group_empty_light.png and /dev/null differ diff --git a/assets/images/wallet_group_light.png b/assets/images/wallet_group_light.png new file mode 100644 index 000000000..7827971e7 Binary files /dev/null and b/assets/images/wallet_group_light.png differ diff --git a/assets/images/wallet_group_options_dark.png b/assets/images/wallet_group_options_dark.png deleted file mode 100644 index 479aac57c..000000000 Binary files a/assets/images/wallet_group_options_dark.png and /dev/null differ diff --git a/assets/images/wallet_group_options_light.png b/assets/images/wallet_group_options_light.png deleted file mode 100644 index 308930520..000000000 Binary files a/assets/images/wallet_group_options_light.png and /dev/null differ diff --git a/assets/images/wallet_name.png b/assets/images/wallet_name.png new file mode 100644 index 000000000..f586682bd Binary files /dev/null and b/assets/images/wallet_name.png differ diff --git a/assets/images/wallet_name_light.png b/assets/images/wallet_name_light.png new file mode 100644 index 000000000..0199c1b30 Binary files /dev/null and b/assets/images/wallet_name_light.png differ diff --git a/assets/images/wallet_type.png b/assets/images/wallet_type.png new file mode 100644 index 000000000..4e0eba8b5 Binary files /dev/null and b/assets/images/wallet_type.png differ diff --git a/assets/images/wallet_type_light.png b/assets/images/wallet_type_light.png new file mode 100644 index 000000000..e36c0d3aa Binary files /dev/null and b/assets/images/wallet_type_light.png differ diff --git a/assets/images/wallet_type_wallet_dark.png b/assets/images/wallet_type_wallet_dark.png deleted file mode 100644 index b840f5547..000000000 Binary files a/assets/images/wallet_type_wallet_dark.png and /dev/null differ diff --git a/assets/images/wallet_type_wallet_light.png b/assets/images/wallet_type_wallet_light.png deleted file mode 100644 index ee759a109..000000000 Binary files a/assets/images/wallet_type_wallet_light.png and /dev/null differ diff --git a/assets/images/wallets.png b/assets/images/wallets.png deleted file mode 100644 index 62ea20039..000000000 Binary files a/assets/images/wallets.png and /dev/null differ diff --git a/assets/images/welcome.png b/assets/images/welcome.png new file mode 100644 index 000000000..f1132d253 Binary files /dev/null and b/assets/images/welcome.png differ diff --git a/assets/images/welcome_dark_theme.svg b/assets/images/welcome_dark_theme.svg deleted file mode 100644 index 8f60c931a..000000000 --- a/assets/images/welcome_dark_theme.svg +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/welcome_light.png b/assets/images/welcome_light.png new file mode 100644 index 000000000..6feff85d1 Binary files /dev/null and b/assets/images/welcome_light.png differ diff --git a/assets/images/welcome_light_theme.svg b/assets/images/welcome_light_theme.svg deleted file mode 100644 index 178b2853d..000000000 --- a/assets/images/welcome_light_theme.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/assets/images/welcome_wallet_dark.png b/assets/images/welcome_wallet_dark.png deleted file mode 100644 index 771a600d3..000000000 Binary files a/assets/images/welcome_wallet_dark.png and /dev/null differ diff --git a/assets/images/welcome_wallet_light.png b/assets/images/welcome_wallet_light.png deleted file mode 100644 index 2a738be0b..000000000 Binary files a/assets/images/welcome_wallet_light.png and /dev/null differ diff --git a/assets/images/wyre-icon.png b/assets/images/wyre-icon.png new file mode 100644 index 000000000..a2810948e Binary files /dev/null and b/assets/images/wyre-icon.png differ diff --git a/assets/images/wyre.png b/assets/images/wyre.png new file mode 100644 index 000000000..a16bbdc8b Binary files /dev/null and b/assets/images/wyre.png differ diff --git a/assets/images/xoswap.svg b/assets/images/xoswap.svg deleted file mode 100644 index ef83c58b1..000000000 --- a/assets/images/xoswap.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/yat_crypto.png b/assets/images/yat_crypto.png new file mode 100644 index 000000000..fbd5d2483 Binary files /dev/null and b/assets/images/yat_crypto.png differ diff --git a/assets/images/zano_icon.png b/assets/images/zano_icon.png deleted file mode 100644 index fd48fd6a5..000000000 Binary files a/assets/images/zano_icon.png and /dev/null differ diff --git a/assets/nano_node_list.yml b/assets/nano_node_list.yml index cda931b5e..be550177e 100644 --- a/assets/nano_node_list.yml +++ b/assets/nano_node_list.yml @@ -1,9 +1,9 @@ - uri: nano.nownodes.io useSSL: true + is_default: true - uri: rpc.nano.to - is_default: true useSSL: true - uri: node.nautilus.io diff --git a/assets/node_list.yml b/assets/node_list.yml index 917dadfd9..49cc00a94 100644 --- a/assets/node_list.yml +++ b/assets/node_list.yml @@ -13,3 +13,9 @@ - uri: nodes.hashvault.pro:18081 is_default: false +- + uri: node.c3pool.com:18081 + is_default: false +- + uri: node.community.rino.io:18081 + is_default: false diff --git a/assets/polygon_node_list.yml b/assets/polygon_node_list.yml index 3b2cdcdc3..34504269d 100644 --- a/assets/polygon_node_list.yml +++ b/assets/polygon_node_list.yml @@ -1,10 +1,6 @@ - uri: polygon-rpc.com - - uri: polygon-bor-rpc.publicnode.com - useSSL: true - isDefault: true + uri: polygon-bor.publicnode.com - - uri: polygon.llamarpc.com -- - uri: matic.nownodes.io \ No newline at end of file + uri: polygon.llamarpc.com \ No newline at end of file diff --git a/assets/solana_node_list.yml b/assets/solana_node_list.yml index 3ba74d980..e5641d3f8 100644 --- a/assets/solana_node_list.yml +++ b/assets/solana_node_list.yml @@ -1,13 +1,10 @@ - uri: rpc.ankr.com + is_default: true useSSL: true - uri: api.mainnet-beta.solana.com:443 useSSL: true - uri: solana-rpc.publicnode.com:443 - useSSL: true -- - uri: solana-mainnet.core.chainstack.com - useSSL: true - is_default: true \ No newline at end of file + useSSL: true \ No newline at end of file diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index faf57258a..556010062 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,2 @@ -Add built-in Tor support (experimental) -Ledger improvements -UI/UX improvements -Bug fixes \ No newline at end of file +UI/UX enhancements +Bug fixes and app improvements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index c49b895e3..556010062 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,9 +1,2 @@ -Add built-in Tor support (experimental) -Add dEuro investments -Solana fixes/enhancements -Polygon fixes/enhancements -WalletConnect improvements -Ledger improvements -Payjoin improvements -UI/UX improvements -Bug fixes \ No newline at end of file +UI/UX enhancements +Bug fixes and app improvements \ No newline at end of file diff --git a/assets/tron_node_list.yml b/assets/tron_node_list.yml index 1e34de712..f9fd91179 100644 --- a/assets/tron_node_list.yml +++ b/assets/tron_node_list.yml @@ -4,8 +4,9 @@ useSSL: true - uri: api.trongrid.io - is_default: true + is_default: false useSSL: true - uri: trx.nownodes.io + is_default: true useSSL: true \ No newline at end of file diff --git a/assets/zano_node_list.yml b/assets/zano_node_list.yml deleted file mode 100644 index f7b874fcb..000000000 --- a/assets/zano_node_list.yml +++ /dev/null @@ -1,7 +0,0 @@ -- - uri: 37.27.100.59:10500 - useSSL: false -- - uri: zano.cakewallet.com:11211 - is_default: true - useSSL: false \ No newline at end of file diff --git a/build-guide-linux.md b/build-guide-linux.md new file mode 100644 index 000000000..99c2ed0c8 --- /dev/null +++ b/build-guide-linux.md @@ -0,0 +1,176 @@ +# Building CakeWallet for Linux + +## Requirements and Setup + +The following are the system requirements to build CakeWallet for your Linux device. + +``` +Ubuntu >= 16.04 +Flutter 3.10.x +``` + +## Building CakeWallet on Linux + +These steps will help you configure and execute a build of CakeWallet from its source code. + +### 1. Installing Package Dependencies + +CakeWallet requires some packages to be installed on your build system. You may easily install them on your build system with the following command: + +`$ sudo apt install build-essential cmake pkg-config git curl autoconf libtool` + +> [!WARNING] +> +> ### Check gcc version +> +> It is needed to use gcc 10 or 9 to successfully link dependencies with flutter.\ +> To check what gcc version you are using: +> +> ```bash +> $ gcc --version +> $ g++ --version +> ``` +> +> If you are using gcc version newer than 10, then you need to downgrade to version 10.4.0: +> +> ```bash +> $ sudo apt install gcc-10 g++-10 +> $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 +> $ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10 +> ``` + +> [!NOTE] +> +> Alternatively, you can use the [nix-shell](https://nixos.org/) with the `gcc10.nix` file\ +> present on `scripts/linux` like so: +> ```bash +> $ nix-shell gcc10.nix +> ``` +> This will get you in a nix environment with all the required dependencies that you can use to build the software from,\ +> and it works in any linux distro. + +### 2. Installing Flutter + +Need to install flutter. For this please check section [How to install flutter on Linux](https://docs.flutter.dev/get-started/install/linux). + +### 3. Verify Installations + +Verify that the Flutter has been correctly installed on your system with the following command: + +`$ flutter doctor` + +The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding. + +``` +Doctor summary (to see all details, run flutter doctor -v): +[✓] Flutter (Channel stable, 3.10.x, on Linux, locale en_US.UTF-8) +``` + +### 4. Acquiring the CakeWallet Source Code + +Download CakeWallet source code + +`$ git clone https://github.com/cake-tech/cake_wallet.git --branch linux/password-direct-input` + +Proceed into the source code before proceeding with the next steps: + +`$ cd cake_wallet/scripts/linux/` + +To configure some project properties run: + +`$ ./cakewallet.sh` + +Build the Monero libraries and their dependencies: + +`$ ./build_all.sh` + +Now the dependencies need to be copied into the CakeWallet project with this command: + +`$ ./setup.sh` + +It is now time to change back to the base directory of the CakeWallet source code: + +`$ cd ../../` + +Install Flutter package dependencies with this command: + +`$ flutter pub get` + +> #### If you will get an error like: +> +> ``` +> The plugin `cw_shared_external` requires your app to be migrated to the Android embedding v2. Follow the steps on the migration doc above and re-run +> this command. +> ``` +> +> Then need to config Android project settings. For this open `scripts/android` (`$ cd scripts/android`) directory and run followed commands: +> +> ``` +> $ source ./app_env.sh cakewallet +> $ ./app_config.sh +> $ cd ../.. +> ``` +> +> Then re-configure Linux project again. For this open `scripts/linux` (`$cd scripts/linux`) directory and run: +> `$ ./cakewallet.sh` +> and back to project root directory: +> `$ cd ../..` +> and fetch dependecies 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: + +`$ dart run tool/generate_new_secrets.dart` + +We will generate mobx models for the project. + +`$ ./model_generator.sh` + +Then we need to generate localization files. + +`$ dart run tool/generate_localization.dart` + +### 5. Build! + +`$ flutter build linux --release` + +Path to executable file will be: + +`build/linux/x64/release/bundle/cake_wallet` + +> ### Troubleshooting +> +> If you got an error while building the application with `$ flutter build linux --release` command, add `-v` argument to the command (`$ flutter build linux -v --release`) to get details.\ +> If you got in flutter build logs: undefined reference to `hid_free_enumeration`, or another error with undefined reference to `hid_*`, then rebuild monero lib without hidapi lib. Check does exists `libhidapi-dev` in your scope and remove it from your scope for build without it. + +# Flatpak + +For package the built application into flatpak you need firstly to install `flatpak` and `flatpak-builder`: + +`$ sudo apt install flatpak flatpak-builder` + +Then need to [add flathub](https://flatpak.org/setup/Ubuntu) (or just `$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo`). Then need to install freedesktop runtime and sdk: + +`$ flatpak install flathub org.freedesktop.Platform//22.08 org.freedesktop.Sdk//22.08` + +To build with using of `flatpak-build` directory run next: + +`$ flatpak-builder --force-clean flatpak-build com.cakewallet.CakeWallet.yml` + +And then export bundle: + +`$ flatpak build-export export flatpak-build` + +`$ flatpak build-bundle export cake_wallet.flatpak com.cakewallet.CakeWallet` + +Result file: `cake_wallet.flatpak` should be generated in the current directory. + +For install generated flatpak file use: + +`$ flatpak --user install cake_wallet.flatpak` + +For run the installed application run: + +`$ flatpak run com.cakewallet.CakeWallet` + +Copyright (c) 2023 Cake Technologies LLC. diff --git a/build-guide-win.md b/build-guide-win.md new file mode 100644 index 000000000..6ace961af --- /dev/null +++ b/build-guide-win.md @@ -0,0 +1,38 @@ +# Building CakeWallet for Windows + +## Requirements and Setup + +The following are the system requirements to build CakeWallet for your Windows PC. + +``` +Windows 10 or later (64-bit), x86-64 based +Flutter 3 or above +``` + +## Building CakeWallet on Windows + +These steps will help you configure and execute a build of CakeWallet from its source code. + +### 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 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: +`$ 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) + +### 3. Build Monero, Monero_c and their dependencies + +For use monero in the application need to build Monero wrapper - Monero_C which will be used by monero.dart package. For that need to run shell (bash - typically same named utility should be available after WSL is enabled in your system) with previously installed WSL, then change current directory to the application project directory with your used shell and then change current directory to `scripts/windows`: `$ cd scripts/windows`. Run build script: `$ ./build_all.sh`. + +### 4. Configure and build CakeWallet application + +To configure the application open directory where you have downloaded or unarchived CakeWallet sources and run `cakewallet.bat`. +Or if you used WSL and have active shell session you can run `$ ./cakewallet.sh` script in `scripts/windows` which will run `cakewallet.bat` in WSL. +After execution of `cakewallet.bat` you should to get `Cake Wallet.zip` in project root directory which will contains `CakeWallet.exe` file and another needed files for run the application. Now you can extract files from `Cake Wallet.zip` archive and run the application. diff --git a/com.cakewallet.CakeWallet.yml b/com.cakewallet.CakeWallet.yml index 6a19c3dda..83efa1388 100644 --- a/com.cakewallet.CakeWallet.yml +++ b/com.cakewallet.CakeWallet.yml @@ -1,6 +1,6 @@ app-id: com.cakewallet.CakeWallet runtime: org.freedesktop.Platform -runtime-version: '24.08' +runtime-version: '22.08' sdk: org.freedesktop.Sdk command: cake_wallet separate-locales: false @@ -15,6 +15,8 @@ finish-args: modules: - name: cake_wallet buildsystem: simple + only-arches: + - x86_64 build-commands: - "cp -R bundle /app/cake_wallet" - "chmod +x /app/cake_wallet/cake_wallet" diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index 0d985b237..73bc101c4 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -2,37 +2,22 @@ import 'package:bitcoin_base/bitcoin_base.dart'; String addressFromOutputScript(Script script, BasedUtxoNetwork network) { try { - return addressFromScript(script, network).toAddress(network); + switch (script.getAddressType()) { + case P2pkhAddressType.p2pkh: + return P2pkhAddress.fromScriptPubkey(script: script).toAddress(network); + case P2shAddressType.p2pkInP2sh: + return P2shAddress.fromScriptPubkey(script: script).toAddress(network); + case SegwitAddresType.p2wpkh: + return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network); + case P2shAddressType.p2pkhInP2sh: + return P2shAddress.fromScriptPubkey(script: script).toAddress(network); + case SegwitAddresType.p2wsh: + return P2wshAddress.fromScriptPubkey(script: script).toAddress(network); + case SegwitAddresType.p2tr: + return P2trAddress.fromScriptPubkey(script: script).toAddress(network); + default: + } } catch (_) {} return ''; } - -BitcoinBaseAddress addressFromScript(Script script, - [BasedUtxoNetwork network = BitcoinNetwork.mainnet]) { - final addressType = script.getAddressType(); - if (addressType == null) { - throw ArgumentError("Invalid script"); - } - - switch (addressType) { - case P2pkhAddressType.p2pkh: - return P2pkhAddress.fromScriptPubkey( - script: script, network: BitcoinNetwork.mainnet); - case P2shAddressType.p2pkhInP2sh: - case P2shAddressType.p2pkInP2sh: - return P2shAddress.fromScriptPubkey( - script: script, network: BitcoinNetwork.mainnet); - case SegwitAddresType.p2wpkh: - return P2wpkhAddress.fromScriptPubkey( - script: script, network: BitcoinNetwork.mainnet); - case SegwitAddresType.p2wsh: - return P2wshAddress.fromScriptPubkey( - script: script, network: BitcoinNetwork.mainnet); - case SegwitAddresType.p2tr: - return P2trAddress.fromScriptPubkey( - script: script, network: BitcoinNetwork.mainnet); - } - - throw ArgumentError("Invalid script"); -} diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index 1509f913a..7e4b5f58f 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:mobx/mobx.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; @@ -17,7 +16,7 @@ abstract class BaseBitcoinAddressRecord { }) : _txCount = txCount, _balance = balance, _name = name, - _isUsed = Observable(isUsed); + _isUsed = isUsed; @override bool operator ==(Object o) => o is BaseBitcoinAddressRecord && address == o.address; @@ -28,7 +27,7 @@ abstract class BaseBitcoinAddressRecord { int _txCount; int _balance; String _name; - final Observable _isUsed; + bool _isUsed; BasedUtxoNetwork? network; int get txCount => _txCount; @@ -41,9 +40,9 @@ abstract class BaseBitcoinAddressRecord { set balance(int value) => _balance = value; - bool get isUsed => _isUsed.value; + bool get isUsed => _isUsed; - void setAsUsed() => _isUsed.value = true; + void setAsUsed() => _isUsed = true; void setNewName(String label) => _name = label; int get hashCode => address.hashCode; diff --git a/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart b/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart index c8715b239..a02c51c69 100644 --- a/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart @@ -6,7 +6,6 @@ import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/hardware/hardware_account_data.dart'; import 'package:ledger_bitcoin/ledger_bitcoin.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; -import 'package:cw_core/utils/print_verbose.dart'; class BitcoinHardwareWalletService { BitcoinHardwareWalletService(this.ledgerConnection); diff --git a/cw_bitcoin/lib/bitcoin_transaction_credentials.dart b/cw_bitcoin/lib/bitcoin_transaction_credentials.dart index 7d6894e14..01e905fb0 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_credentials.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_credentials.dart @@ -3,17 +3,11 @@ import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coin_type.dart'; class BitcoinTransactionCredentials { - BitcoinTransactionCredentials( - this.outputs, { - required this.priority, - this.feeRate, - this.coinTypeToSpendFrom = UnspentCoinType.any, - this.payjoinUri, - }); + BitcoinTransactionCredentials(this.outputs, + {required this.priority, this.feeRate, this.coinTypeToSpendFrom = UnspentCoinType.any}); final List outputs; final BitcoinTransactionPriority? priority; final int? feeRate; final UnspentCoinType coinTypeToSpendFrom; - final String? payjoinUri; } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 9231022f6..908897845 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -3,33 +3,22 @@ import 'dart:convert'; import 'package:bip39/bip39.dart' as bip39; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; -import 'package:cw_bitcoin/address_from_output.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; +import 'package:cw_bitcoin/psbt_transaction_builder.dart'; +import 'package:cw_core/encryption_file_utils.dart'; +import 'package:cw_bitcoin/electrum_derivations.dart'; import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; -import 'package:cw_bitcoin/electrum_derivations.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; -import 'package:cw_bitcoin/payjoin/manager.dart'; -import 'package:cw_bitcoin/payjoin/storage.dart'; -import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; -import 'package:cw_bitcoin/psbt/signer.dart'; -import 'package:cw_bitcoin/psbt/transaction_builder.dart'; -import 'package:cw_bitcoin/psbt/v0_deserialize.dart'; -import 'package:cw_bitcoin/psbt/v0_finalizer.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/encryption_file_utils.dart'; -import 'package:cw_core/payjoin_session.dart'; -import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_keys_file.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:ledger_bitcoin/ledger_bitcoin.dart'; -import 'package:ledger_bitcoin/psbt.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; import 'package:mobx/mobx.dart'; @@ -42,7 +31,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, - required Box payjoinBox, required EncryptionFileUtils encryptionFileUtils, Uint8List? seedBytes, String? mnemonic, @@ -83,21 +71,20 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { // String derivationPath = walletInfo.derivationInfo!.derivationPath!; // String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1"; // final hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType); - - payjoinManager = PayjoinManager(PayjoinStorage(payjoinBox), this); - walletAddresses = BitcoinWalletAddresses(walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - initialSilentAddresses: initialSilentAddresses, - initialSilentAddressIndex: initialSilentAddressIndex, - mainHd: hd, - sideHd: accountHD.childKey(Bip32KeyIndex(1)), - network: networkParam ?? network, - masterHd: - seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null, - isHardwareWallet: walletInfo.isHardwareWallet, - payjoinManager: payjoinManager); + walletAddresses = BitcoinWalletAddresses( + walletInfo, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + initialSilentAddresses: initialSilentAddresses, + initialSilentAddressIndex: initialSilentAddressIndex, + mainHd: hd, + sideHd: accountHD.childKey(Bip32KeyIndex(1)), + network: networkParam ?? network, + masterHd: + seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null, + isHardwareWallet: walletInfo.isHardwareWallet, + ); autorun((_) { this.walletAddresses.isEnabledAutoGenerateSubaddress = @@ -105,15 +92,11 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { }); } - @override - bool get hasRescan => true; - static Future create({ required String mnemonic, required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, - required Box payjoinBox, required EncryptionFileUtils encryptionFileUtils, String? passphrase, String? addressPageType, @@ -136,11 +119,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { break; case DerivationType.electrum: default: - seedBytes = - await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? ""); + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? ""); break; } - return BitcoinWallet( mnemonic: mnemonic, passphrase: passphrase ?? "", @@ -157,7 +138,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialChangeAddressIndex: initialChangeAddressIndex, addressPageType: addressPageType, networkParam: network, - payjoinBox: payjoinBox, ); } @@ -165,7 +145,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String name, required WalletInfo walletInfo, required Box unspentCoinsInfo, - required Box payjoinBox, required String password, required EncryptionFileUtils encryptionFileUtils, required bool alwaysScan, @@ -222,8 +201,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { if (mnemonic != null) { switch (walletInfo.derivationInfo!.derivationType) { case DerivationType.electrum: - seedBytes = - await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? ""); + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? ""); break; case DerivationType.bip39: default: @@ -236,24 +214,24 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { } return BitcoinWallet( - mnemonic: mnemonic, - xpub: keysData.xPub, - password: password, - passphrase: passphrase, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp?.addresses, - initialSilentAddresses: snp?.silentAddresses, - initialSilentAddressIndex: snp?.silentAddressIndex ?? 0, - initialBalance: snp?.balance, - encryptionFileUtils: encryptionFileUtils, - seedBytes: seedBytes, - initialRegularAddressIndex: snp?.regularAddressIndex, - initialChangeAddressIndex: snp?.changeAddressIndex, - addressPageType: snp?.addressPageType, - networkParam: network, - alwaysScan: alwaysScan, - payjoinBox: payjoinBox); + mnemonic: mnemonic, + xpub: keysData.xPub, + password: password, + passphrase: passphrase, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp?.addresses, + initialSilentAddresses: snp?.silentAddresses, + initialSilentAddressIndex: snp?.silentAddressIndex ?? 0, + initialBalance: snp?.balance, + encryptionFileUtils: encryptionFileUtils, + seedBytes: seedBytes, + initialRegularAddressIndex: snp?.regularAddressIndex, + initialChangeAddressIndex: snp?.changeAddressIndex, + addressPageType: snp?.addressPageType, + networkParam: network, + alwaysScan: alwaysScan, + ); } LedgerConnection? _ledgerConnection; @@ -267,30 +245,19 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { } @override - Future close({bool shouldCleanup = false}) async { - payjoinManager.cleanupSessions(); - super.close(shouldCleanup: shouldCleanup); - } - - late final PayjoinManager payjoinManager; - - bool get isPayjoinAvailable => unspentCoinsInfo.values - .where((element) => - element.walletId == id && element.isSending && !element.isFrozen) - .isNotEmpty; - - Future buildPsbt({ + Future buildHardwareWalletTransaction({ required List outputs, required BigInt fee, required BasedUtxoNetwork network, required List utxos, required Map publicKeys, - required Uint8List masterFingerprint, String? memo, bool enableRBF = false, BitcoinOrdering inputOrdering = BitcoinOrdering.bip69, BitcoinOrdering outputOrdering = BitcoinOrdering.bip69, }) async { + final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint(); + final psbtReadyInputs = []; for (final utxo in utxos) { final rawTx = @@ -308,128 +275,13 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { )); } - return PSBTTransactionBuild( - inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF) - .psbt; - } + final psbt = PSBTTransactionBuild( + inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF); - @override - Future buildHardwareWalletTransaction({ - required List outputs, - required BigInt fee, - required BasedUtxoNetwork network, - required List utxos, - required Map publicKeys, - String? memo, - bool enableRBF = false, - BitcoinOrdering inputOrdering = BitcoinOrdering.bip69, - BitcoinOrdering outputOrdering = BitcoinOrdering.bip69, - }) async { - final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint(); - - final psbt = await buildPsbt( - outputs: outputs, - fee: fee, - network: network, - utxos: utxos, - publicKeys: publicKeys, - masterFingerprint: masterFingerprint, - memo: memo, - enableRBF: enableRBF, - inputOrdering: inputOrdering, - outputOrdering: outputOrdering, - ); - - final rawHex = await _bitcoinLedgerApp!.signPsbt(psbt: psbt); + final rawHex = await _bitcoinLedgerApp!.signPsbt(psbt: psbt.psbt); return BtcTransaction.fromRaw(BytesUtils.toHexString(rawHex)); } - @override - Future createTransaction(Object credentials) async { - credentials = credentials as BitcoinTransactionCredentials; - - final tx = (await super.createTransaction(credentials)) - as PendingBitcoinTransaction; - - final payjoinUri = credentials.payjoinUri; - if (payjoinUri == null) return tx; - - final transaction = await buildPsbt( - utxos: tx.utxos, - outputs: tx.outputs - .map((e) => BitcoinOutput( - address: addressFromScript(e.scriptPubKey), - value: e.amount, - isSilentPayment: e.isSilentPayment, - isChange: e.isChange, - )) - .toList(), - fee: BigInt.from(tx.fee), - network: network, - memo: credentials.outputs.first.memo, - outputOrdering: BitcoinOrdering.none, - enableRBF: true, - publicKeys: tx.publicKeys!, - masterFingerprint: Uint8List(0)); - - final originalPsbt = await signPsbt( - base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys()); - - tx.commitOverride = () async { - final sender = await payjoinManager.initSender( - payjoinUri, originalPsbt, int.parse(tx.feeRate)); - payjoinManager.spawnNewSender( - sender: sender, pjUrl: payjoinUri, amount: BigInt.from(tx.amount)); - }; - - return tx; - } - - List getUtxoWithPrivateKeys() => unspentCoins - .where((e) => (e.isSending && !e.isFrozen)) - .map((unspent) => UtxoWithPrivateKey.fromUnspent(unspent, this)) - .toList(); - - Future commitPsbt(String finalizedPsbt) { - final psbt = PsbtV2()..deserializeV0(base64.decode(finalizedPsbt)); - - final btcTx = - BtcTransaction.fromRaw(BytesUtils.toHexString(psbt.extract())); - - return PendingBitcoinTransaction( - btcTx, - type, - electrumClient: electrumClient, - amount: 0, - fee: 0, - feeRate: "", - network: network, - hasChange: true, - ).commit(); - } - - Future signPsbt( - String preProcessedPsbt, List utxos) async { - final psbt = PsbtV2()..deserializeV0(base64Decode(preProcessedPsbt)); - - await psbt.signWithUTXO(utxos, (txDigest, utxo, key, sighash) { - return utxo.utxo.isP2tr() - ? key.signTapRoot( - txDigest, - sighash: sighash, - tweak: utxo.utxo.isSilentPayment != true, - ) - : key.signInput(txDigest, sigHash: sighash); - }, (txId, vout) async { - final txHex = await electrumClient.getTransactionHex(hash: txId); - final output = BtcTransaction.fromRaw(txHex).outputs[vout]; - return TaprootAmountScriptPair(output.amount, output.scriptPubKey); - }); - - psbt.finalizeV0(); - return base64Encode(psbt.asPsbtV0()); - } - @override Future signMessage(String message, {String? address = null}) async { if (walletInfo.isHardwareWallet) { diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index d84d958be..04a3cae36 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -1,13 +1,9 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:blockchain_utils/bip/bip/bip32/bip32.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:cw_bitcoin/payjoin/manager.dart'; import 'package:cw_bitcoin/utils.dart'; -import 'package:cw_core/unspent_coin_type.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; -import 'package:payjoin_flutter/receive.dart' as payjoin; part 'bitcoin_wallet_addresses.g.dart'; @@ -20,7 +16,6 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S required super.sideHd, required super.network, required super.isHardwareWallet, - required this.payjoinManager, super.initialAddresses, super.initialRegularAddressIndex, super.initialChangeAddressIndex, @@ -29,19 +24,9 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S super.masterHd, }) : super(walletInfo); - final PayjoinManager payjoinManager; - - payjoin.Receiver? currentPayjoinReceiver; - - @observable - String? payjoinEndpoint = null; - @override String getAddress( - {required int index, - required Bip32Slip10Secp256k1 hd, - BitcoinAddressType? addressType, - UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) { + {required int index, required Bip32Slip10Secp256k1 hd, BitcoinAddressType? addressType}) { if (addressType == P2pkhAddressType.p2pkh) return generateP2PKHAddress(hd: hd, index: index, network: network); @@ -56,33 +41,4 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S return generateP2WPKHAddress(hd: hd, index: index, network: network); } - - @action - Future initPayjoin() async { - try { - await payjoinManager.initPayjoin(); - currentPayjoinReceiver = await payjoinManager.getUnusedReceiver(primaryAddress); - payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint(); - - payjoinManager.resumeSessions(); - } catch (e) { - printV(e); - // Ignore Connectivity errors - if (!e.toString().contains("error sending request for url")) rethrow; - } - } - - @action - Future newPayjoinReceiver() async { - try { - currentPayjoinReceiver = await payjoinManager.getUnusedReceiver(primaryAddress); - payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint(); - - payjoinManager.spawnReceiver(receiver: currentPayjoinReceiver!); - } catch (e) { - printV(e); - // Ignore Connectivity errors - if (!e.toString().contains("error sending request for url")) rethrow; - } - } } diff --git a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart index 177d61e87..a1b1418b8 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart @@ -11,11 +11,13 @@ class BitcoinNewWalletCredentials extends WalletCredentials { String? derivationPath, String? passphrase, this.mnemonic, + String? parentAddress, }) : super( name: name, walletInfo: walletInfo, password: password, passphrase: passphrase, + parentAddress: parentAddress, ); final String? mnemonic; diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 317b25bcd..7ee1534bf 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -5,7 +5,6 @@ import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart'; import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_core/encryption_file_utils.dart'; -import 'package:cw_core/payjoin_session.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_service.dart'; @@ -22,12 +21,10 @@ class BitcoinWalletService extends WalletService< BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials, BitcoinRestoreWalletFromHardware> { - BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, - this.payjoinSessionSource, this.alwaysScan, this.isDirect); + BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect); final Box walletInfoSource; final Box unspentCoinsInfoSource; - final Box payjoinSessionSource; final bool alwaysScan; final bool isDirect; @@ -58,7 +55,6 @@ class BitcoinWalletService extends WalletService< passphrase: credentials.passphrase, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, - payjoinBox: payjoinSessionSource, network: network, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -83,7 +79,6 @@ class BitcoinWalletService extends WalletService< name: name, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, - payjoinBox: payjoinSessionSource, alwaysScan: alwaysScan, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -97,7 +92,6 @@ class BitcoinWalletService extends WalletService< name: name, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, - payjoinBox: payjoinSessionSource, alwaysScan: alwaysScan, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -132,7 +126,6 @@ class BitcoinWalletService extends WalletService< name: currentName, walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource, - payjoinBox: payjoinSessionSource, alwaysScan: alwaysScan, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -154,6 +147,7 @@ class BitcoinWalletService extends WalletService< credentials.walletInfo?.network = network.value; credentials.walletInfo?.derivationInfo?.derivationPath = credentials.hwAccountData.derivationPath; + final wallet = await BitcoinWallet( password: credentials.password!, xpub: credentials.hwAccountData.xpub, @@ -161,7 +155,6 @@ class BitcoinWalletService extends WalletService< unspentCoinsInfo: unspentCoinsInfoSource, networkParam: network, encryptionFileUtils: encryptionFileUtilsFor(isDirect), - payjoinBox: payjoinSessionSource, ); await wallet.save(); await wallet.init(); @@ -189,7 +182,6 @@ class BitcoinWalletService extends WalletService< mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, - payjoinBox: payjoinSessionSource, network: network, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 2ddd30df6..df8e14119 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -4,9 +4,6 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_socket/abstract.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:flutter/foundation.dart'; import 'package:rxdart/rxdart.dart'; @@ -44,7 +41,7 @@ class ElectrumClient { static const aliveTimerDuration = Duration(seconds: 4); bool get isConnected => _isConnected; - ProxySocket? socket; + Socket? socket; void Function(ConnectionStatus)? onConnectionStatusChange; int _id; final Map _tasks; @@ -74,11 +71,18 @@ class ElectrumClient { } catch (_) {} socket = null; - final ssl = !(useSSL == false || (useSSL == null && uri.toString().contains("btc-electrum"))); try { - socket = await ProxyWrapper().getSocksSocket(ssl, host, port, connectionTimeout: connectionTimeout); + if (useSSL == false || (useSSL == null && uri.toString().contains("btc-electrum"))) { + socket = await Socket.connect(host, port, timeout: connectionTimeout); + } else { + socket = await SecureSocket.connect( + host, + port, + timeout: connectionTimeout, + onBadCertificate: (_) => true, + ); + } } catch (e) { - printV("connect: $e"); if (e is HandshakeException) { useSSL = !(useSSL ?? false); } @@ -100,6 +104,7 @@ class ElectrumClient { // use ping to determine actual connection status since we could've just not timed out yet: // _setConnectionStatus(ConnectionStatus.connected); + socket!.listen( (Uint8List event) { try { @@ -112,17 +117,17 @@ class ElectrumClient { _parseResponse(message); } } catch (e) { - printV("socket.listen: $e"); + print("socket.listen: $e"); } }, onError: (Object error) { final errorMsg = error.toString(); - printV(errorMsg); + print(errorMsg); unterminatedString = ''; socket = null; }, onDone: () { - printV("SOCKET CLOSED!!!!!"); + print("SOCKET CLOSED!!!!!"); unterminatedString = ''; try { if (host == socket?.address.host || socket == null) { @@ -131,7 +136,7 @@ class ElectrumClient { socket = null; } } catch (e) { - printV("onDone: $e"); + print("onDone: $e"); } }, cancelOnError: true, @@ -176,7 +181,7 @@ class ElectrumClient { unterminatedString = ''; } } catch (e) { - printV("parse $e"); + print("parse $e"); } } @@ -229,21 +234,21 @@ class ElectrumClient { return []; }); - Future>?> getListUnspent(String scriptHash) async { - final result = await call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]); + Future>> getListUnspent(String scriptHash) => + call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]) + .then((dynamic result) { + if (result is List) { + return result.map((dynamic val) { + if (val is Map) { + return val; + } - if (result is List) { - return result.map((dynamic val) { - if (val is Map) { - return val; + return {}; + }).toList(); } - return {}; - }).toList(); - } - - return null; - } + return []; + }); Future>> getMempool(String scriptHash) => call(method: 'blockchain.scripthash.get_mempool', params: [scriptHash]) @@ -398,7 +403,7 @@ class ElectrumClient { } on RequestFailedTimeoutException catch (_) { return null; } catch (e) { - printV("getCurrentBlockChainTip: ${e.toString()}"); + print("getCurrentBlockChainTip: ${e.toString()}"); return null; } } @@ -429,7 +434,7 @@ class ElectrumClient { return subscription; } catch (e) { - printV("subscribe $e"); + print("subscribe $e"); return null; } } @@ -468,7 +473,7 @@ class ElectrumClient { return completer.future; } catch (e) { - printV("callWithTimeout $e"); + print("callWithTimeout $e"); rethrow; } } diff --git a/cw_bitcoin/lib/electrum_balance.dart b/cw_bitcoin/lib/electrum_balance.dart index aeb06f1f0..ebd2f06ae 100644 --- a/cw_bitcoin/lib/electrum_balance.dart +++ b/cw_bitcoin/lib/electrum_balance.dart @@ -39,7 +39,7 @@ class ElectrumBalance extends Balance { int secondUnconfirmed = 0; @override - String get formattedAvailableBalance => bitcoinAmountToString(amount: ((confirmed + unconfirmed) - frozen) ); + String get formattedAvailableBalance => bitcoinAmountToString(amount: confirmed - frozen); @override String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed); @@ -58,13 +58,13 @@ class ElectrumBalance extends Balance { @override String get formattedFullAvailableBalance => - bitcoinAmountToString(amount: (confirmed + unconfirmed) + secondConfirmed - frozen); + bitcoinAmountToString(amount: confirmed + secondConfirmed - frozen); String toJSON() => json.encode({ 'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen, 'secondConfirmed': secondConfirmed, - 'secondUnconfirmed': secondUnconfirmed, + 'secondUnconfirmed': secondUnconfirmed }); } diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index d096d0e7b..b688f097b 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -5,7 +5,6 @@ import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/utils/file.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_history.dart'; @@ -31,10 +30,7 @@ abstract class ElectrumTransactionHistoryBase String _password; int _height; - Future init() async { - clear(); - await _load(); - } + Future init() async => await _load(); @override void addOne(ElectrumTransactionInfo transaction) => transactions[transaction.id] = transaction; @@ -55,7 +51,7 @@ abstract class ElectrumTransactionHistoryBase final data = json.encode({'height': _height, 'transactions': txjson}); await encryptionFileUtils.write(path: path, password: _password, data: data); } catch (e) { - printV('Error while save bitcoin transaction history: ${e.toString()}'); + print('Error while save bitcoin transaction history: ${e.toString()}'); } } @@ -92,7 +88,7 @@ abstract class ElectrumTransactionHistoryBase _height = content['height'] as int; } catch (e) { - printV(e); + print(e); } } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index bb9cea1bc..771d135a0 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -4,10 +4,6 @@ import 'dart:io'; import 'dart:isolate'; import 'package:bitcoin_base/bitcoin_base.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; -import 'package:cw_bitcoin/bitcoin_amount_format.dart'; -import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_bitcoin/bitcoin_wallet.dart'; import 'package:cw_bitcoin/litecoin_wallet.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -50,6 +46,7 @@ import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; import 'package:sp_scanner/sp_scanner.dart'; import 'package:hex/hex.dart'; +import 'package:http/http.dart' as http; part 'electrum_wallet.g.dart'; @@ -479,12 +476,11 @@ abstract class ElectrumWalletBase if (alwaysScan == true) { _setListeners(walletInfo.restoreHeight); } else { - if (syncStatus is LostConnectionSyncStatus) return; syncStatus = SyncedSyncStatus(); } } catch (e, stacktrace) { - printV(stacktrace); - printV("startSync $e"); + print(stacktrace); + print("startSync $e"); syncStatus = FailedSyncStatus(); } } @@ -493,9 +489,10 @@ abstract class ElectrumWalletBase Future updateFeeRates() async { if (await checkIfMempoolAPIIsEnabled() && type == WalletType.bitcoin) { try { - final response = await ProxyWrapper() - .get(clearnetUri: Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended")) - .timeout(Duration(seconds: 15)); + final response = await http + .get(Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended")) + .timeout(Duration(seconds: 5)); + final result = json.decode(response.body) as Map; final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0; int mediumFee = (result['hourFee'] as num?)?.toInt() ?? 0; @@ -509,7 +506,7 @@ abstract class ElectrumWalletBase _feeRates = [slowFee, mediumFee, fastFee]; return; } catch (e) { - printV(e); + print(e); } } @@ -591,8 +588,8 @@ abstract class ElectrumWalletBase await electrumClient.connectToUri(node.uri, useSSL: node.useSSL); } catch (e, stacktrace) { - printV(stacktrace); - printV("connectToNode $e"); + print(stacktrace); + print("connectToNode $e"); syncStatus = FailedSyncStatus(); } } @@ -633,8 +630,8 @@ abstract class ElectrumWalletBase }).toList(); final unconfirmedCoins = availableInputs.where((utx) => utx.confirmations == 0).toList(); - // sort the unconfirmed coins so that mweb coins are last: - availableInputs.sort((a, b) => a.bitcoinAddressRecord.type == SegwitAddresType.mweb ? 1 : -1); + // sort the unconfirmed coins so that mweb coins are first: + availableInputs.sort((a, b) => a.bitcoinAddressRecord.type == SegwitAddresType.mweb ? -1 : 1); for (int i = 0; i < availableInputs.length; i++) { final utx = availableInputs[i]; @@ -843,7 +840,6 @@ abstract class ElectrumWalletBase final changeAddress = await walletAddresses.getChangeAddress( inputs: utxoDetails.availableInputs, outputs: updatedOutputs, - coinTypeToSpendFrom: coinTypeToSpendFrom, ); final address = RegexUtils.addressTypeFromStr(changeAddress.address, network); updatedOutputs.add(BitcoinOutput( @@ -916,10 +912,6 @@ abstract class ElectrumWalletBase } } - // if the amount left for change is less than dust, but not less than 0 - // then add it to the fees - fee += amountLeftForChange; - return EstimatedTxResult( utxos: utxoDetails.utxos, inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos, @@ -996,9 +988,6 @@ abstract class ElectrumWalletBase @override Future createTransaction(Object credentials) async { try { - // start by updating unspent coins - await updateAllUnspents(); - final outputs = []; final transactionCredentials = credentials as BitcoinTransactionCredentials; final hasMultiDestination = transactionCredentials.outputs.length > 1; @@ -1108,7 +1097,6 @@ abstract class ElectrumWalletBase )..addListener((transaction) async { transactionHistory.addOne(transaction); await updateBalance(); - await updateAllUnspents(); }); } @@ -1175,18 +1163,19 @@ abstract class ElectrumWalletBase } }); - return PendingBitcoinTransaction(transaction, type, - electrumClient: electrumClient, - amount: estimatedTx.amount, - fee: estimatedTx.fee, - feeRate: feeRateInt.toString(), - network: network, - hasChange: estimatedTx.hasChange, - isSendAll: estimatedTx.isSendAll, - hasTaprootInputs: hasTaprootInputs, - utxos: estimatedTx.utxos, - publicKeys: estimatedTx.publicKeys) - ..addListener((transaction) async { + return PendingBitcoinTransaction( + transaction, + type, + electrumClient: electrumClient, + amount: estimatedTx.amount, + fee: estimatedTx.fee, + feeRate: feeRateInt.toString(), + network: network, + hasChange: estimatedTx.hasChange, + isSendAll: estimatedTx.isSendAll, + hasTaprootInputs: hasTaprootInputs, + utxos: estimatedTx.utxos, + )..addListener((transaction) async { transactionHistory.addOne(transaction); if (estimatedTx.spendsSilentPayment) { transactionHistory.transactions.values.forEach((tx) { @@ -1200,7 +1189,6 @@ abstract class ElectrumWalletBase .removeWhere((utxo) => estimatedTx.utxos.any((e) => e.utxo.txHash == utxo.hash)); await updateBalance(); - await updateAllUnspents(); }); } catch (e) { throw e; @@ -1356,7 +1344,7 @@ abstract class ElectrumWalletBase } @override - Future close({bool shouldCleanup = false}) async { + Future close({required bool shouldCleanup}) async { try { await _receiveStream?.cancel(); await electrumClient.close(); @@ -1369,10 +1357,6 @@ abstract class ElectrumWalletBase Future updateAllUnspents() async { List updatedUnspentCoins = []; - final previousUnspentCoins = List.from(unspentCoins.where((utxo) => - utxo.bitcoinAddressRecord.type != SegwitAddresType.mweb && - utxo.bitcoinAddressRecord is! BitcoinSilentPaymentAddressRecord)); - if (hasSilentPaymentsScanning) { // Update unspents stored from scanned silent payment transactions transactionHistory.transactions.values.forEach((tx) { @@ -1389,30 +1373,15 @@ abstract class ElectrumWalletBase if (addr is! BitcoinSilentPaymentAddressRecord) addr.balance = 0; }); - final addressFutures = walletAddresses.allAddresses + await Future.wait(walletAddresses.allAddresses .where((element) => element.type != SegwitAddresType.mweb) - .map((address) => fetchUnspent(address)) - .toList(); + .map((address) async { + updatedUnspentCoins.addAll(await fetchUnspent(address)); + })); - final results = await Future.wait(addressFutures); - final failedCount = results.where((result) => result == null).length; - - if (failedCount == 0) { - for (final result in results) { - updatedUnspentCoins.addAll(result!); - } - unspentCoins = updatedUnspentCoins; - } else { - unspentCoins = handleFailedUtxoFetch( - failedCount: failedCount, - previousUnspentCoins: previousUnspentCoins, - updatedUnspentCoins: updatedUnspentCoins, - results: results, - ); - } - - final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId == id); + unspentCoins = updatedUnspentCoins; + + final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id); if (currentWalletUnspentCoins.length != updatedUnspentCoins.length) { unspentCoins.forEach((coin) => addCoinInfo(coin)); @@ -1422,37 +1391,6 @@ abstract class ElectrumWalletBase await _refreshUnspentCoinsInfo(); } - List handleFailedUtxoFetch({ - required int failedCount, - required List previousUnspentCoins, - required List updatedUnspentCoins, - required List?> results, - }) { - if (failedCount == results.length) { - printV("All UTXOs failed to fetch, falling back to previous UTXOs"); - return previousUnspentCoins; - } - - final successfulUtxos = []; - for (final result in results) { - if (result != null) { - successfulUtxos.addAll(result); - } - } - - if (failedCount > 0 && successfulUtxos.isEmpty) { - printV("Some UTXOs failed, but no successful UTXOs, falling back to previous UTXOs"); - return previousUnspentCoins; - } - - if (failedCount > 0) { - printV("Some UTXOs failed, updating with successful UTXOs"); - updatedUnspentCoins.addAll(successfulUtxos); - } - - return updatedUnspentCoins; - } - Future updateCoins(List newUnspentCoins) async { if (newUnspentCoins.isEmpty) { return; @@ -1484,17 +1422,15 @@ abstract class ElectrumWalletBase @action Future updateUnspentsForAddress(BitcoinAddressRecord address) async { final newUnspentCoins = await fetchUnspent(address); - await updateCoins(newUnspentCoins ?? []); + await updateCoins(newUnspentCoins); } @action - Future?> fetchUnspent(BitcoinAddressRecord address) async { + Future> fetchUnspent(BitcoinAddressRecord address) async { + List> unspents = []; List updatedUnspentCoins = []; - final unspents = await electrumClient.getListUnspent(address.getScriptHash(network)); - - // Failed to fetch unspents - if (unspents == null) return null; + unspents = await electrumClient.getListUnspent(address.getScriptHash(network)); await Future.wait(unspents.map((unspent) async { try { @@ -1512,9 +1448,10 @@ abstract class ElectrumWalletBase @action Future addCoinInfo(BitcoinUnspent coin) async { + // Check if the coin is already in the unspentCoinsInfo for the wallet - final existingCoinInfo = unspentCoinsInfo.values - .firstWhereOrNull((element) => element.walletId == walletInfo.id && element == coin); + final existingCoinInfo = unspentCoinsInfo.values.firstWhereOrNull( + (element) => element.walletId == walletInfo.id && element == coin); if (existingCoinInfo == null) { final newInfo = UnspentCoinsInfo( @@ -1536,31 +1473,31 @@ abstract class ElectrumWalletBase Future _refreshUnspentCoinsInfo() async { try { - final List keys = []; + final List keys = []; final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((record) => record.walletId == id); + unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); - for (final element in currentWalletUnspentCoins) { - if (RegexUtils.addressTypeFromStr(element.address, network) is MwebAddress) continue; + if (currentWalletUnspentCoins.isNotEmpty) { + currentWalletUnspentCoins.forEach((element) { + final existUnspentCoins = unspentCoins + .where((coin) => element.hash.contains(coin.hash) && element.vout == coin.vout); - final existUnspentCoins = unspentCoins.where((coin) => element == coin); - - if (existUnspentCoins.isEmpty) { - keys.add(element.key); - } + if (existUnspentCoins.isEmpty) { + keys.add(element.key); + } + }); } if (keys.isNotEmpty) { await unspentCoinsInfo.deleteAll(keys); } } catch (e) { - printV("refreshUnspentCoinsInfo $e"); + print("refreshUnspentCoinsInfo $e"); } } Future cleanUpDuplicateUnspentCoins() async { - final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId == id); + final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id); final Map uniqueUnspentCoins = {}; final List duplicateKeys = []; @@ -1596,8 +1533,7 @@ abstract class ElectrumWalletBase final ownAddresses = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); final receiverAmount = outputs - .where((output) => - !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network))) + .where((output) => !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network))) .fold(0, (sum, output) => sum + output.amount.toInt()); if (receiverAmount == 0) { @@ -1646,7 +1582,7 @@ abstract class ElectrumWalletBase allInputsAmount += outTransaction.amount.toInt(); final addressRecord = - walletAddresses.allAddresses.firstWhere((element) => element.address == address); + walletAddresses.allAddresses.firstWhere((element) => element.address == address); final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network); final privkey = generateECPrivate( hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, @@ -1664,7 +1600,7 @@ abstract class ElectrumWalletBase scriptType: _getScriptType(btcAddress), ), ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), ), ); } @@ -1692,7 +1628,7 @@ abstract class ElectrumWalletBase // Calculate the total amount and fees int totalOutAmount = - outputs.fold(0, (previousValue, output) => previousValue + output.value.toInt()); + outputs.fold(0, (previousValue, output) => previousValue + output.value.toInt()); int currentFee = allInputsAmount - totalOutAmount; int remainingFee = newFee - currentFee; @@ -1748,7 +1684,7 @@ abstract class ElectrumWalletBase vout: utxo.vout, scriptType: _getScriptType(address)), ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), )); allInputsAmount += utxo.value; @@ -1805,11 +1741,11 @@ abstract class ElectrumWalletBase final changeAddresses = walletAddresses.allAddresses.where((element) => element.isHidden); final List changeOutputs = outputs .where((output) => changeAddresses - .any((element) => element.address == output.address.toAddress(network))) + .any((element) => element.address == output.address.toAddress(network))) .toList(); int totalChangeAmount = - changeOutputs.fold(0, (sum, output) => sum + output.value.toInt()); + changeOutputs.fold(0, (sum, output) => sum + output.value.toInt()); // The final amount that the receiver will receive int sendingAmount = allInputsAmount - newFee - totalChangeAmount; @@ -1826,7 +1762,7 @@ abstract class ElectrumWalletBase final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { final key = - privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); if (key == null) { throw Exception("Cannot find private key"); } @@ -1836,6 +1772,7 @@ abstract class ElectrumWalletBase } else { return key.signInput(txDigest, sigHash: sighash); } + }); return PendingBitcoinTransaction( @@ -1848,17 +1785,16 @@ abstract class ElectrumWalletBase hasChange: changeOutputs.isNotEmpty, feeRate: newFee.toString(), )..addListener((transaction) async { - transactionHistory.transactions.values.forEach((tx) { - if (tx.id == hash) { - tx.isReplaced = true; - tx.isPending = false; - transactionHistory.addOne(tx); - } - }); - transactionHistory.addOne(transaction); - await updateBalance(); - await updateAllUnspents(); + transactionHistory.transactions.values.forEach((tx) { + if (tx.id == hash) { + tx.isReplaced = true; + tx.isPending = false; + transactionHistory.addOne(tx); + } }); + transactionHistory.addOne(transaction); + await updateBalance(); + }); } catch (e) { throw e; } @@ -1877,17 +1813,20 @@ abstract class ElectrumWalletBase if (height != null && height > 0 && await checkIfMempoolAPIIsEnabled()) { try { - final blockHash = await ProxyWrapper() - .get(clearnetUri: Uri.parse("https://mempool.cakewallet.com/api/v1/block-height/$height")) - .timeout(Duration(seconds: 15)); + final blockHash = await http.get( + Uri.parse( + "https://mempool.cakewallet.com/api/v1/block-height/$height", + ), + ); if (blockHash.statusCode == 200 && blockHash.body.isNotEmpty && jsonDecode(blockHash.body) != null) { - final blockResponse = await ProxyWrapper() - .get(clearnetUri: Uri.parse("https://mempool.cakewallet.com/api/v1/block/${blockHash}")) - .timeout(Duration(seconds: 15)); - + final blockResponse = await http.get( + Uri.parse( + "https://mempool.cakewallet.com/api/v1/block/${blockHash.body}", + ), + ); if (blockResponse.statusCode == 200 && blockResponse.body.isNotEmpty && jsonDecode(blockResponse.body)['timestamp'] != null) { @@ -1960,11 +1899,6 @@ abstract class ElectrumWalletBase } } - bool isMine(Script script) { - final derivedAddress = addressFromOutputScript(script, network); - return addressesSet.contains(derivedAddress); - } - @override Future> fetchTransactions() async { try { @@ -2001,7 +1935,7 @@ abstract class ElectrumWalletBase return historiesWithDetails; } catch (e) { - printV("fetchTransactions $e"); + print("fetchTransactions $e"); return {}; } } @@ -2125,7 +2059,7 @@ abstract class ElectrumWalletBase } Future updateTransactions() async { - printV("updateTransactions() called!"); + print("updateTransactions() called!"); try { if (_isTransactionUpdating) { return; @@ -2157,8 +2091,8 @@ abstract class ElectrumWalletBase walletAddresses.updateReceiveAddresses(); _isTransactionUpdating = false; } catch (e, stacktrace) { - printV(stacktrace); - printV(e); + print(stacktrace); + print(e); _isTransactionUpdating = false; } } @@ -2176,13 +2110,13 @@ abstract class ElectrumWalletBase try { await _scripthashesUpdateSubject[sh]?.close(); } catch (e) { - printV("failed to close: $e"); + print("failed to close: $e"); } } try { _scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh); } catch (e) { - printV("failed scripthashUpdate: $e"); + print("failed scripthashUpdate: $e"); } _scripthashesUpdateSubject[sh]?.listen((event) async { try { @@ -2192,7 +2126,7 @@ abstract class ElectrumWalletBase await _fetchAddressHistory(address, await getCurrentChainTip()); } catch (e, s) { - printV("sub error: $e"); + print("sub error: $e"); _onError?.call(FlutterErrorDetails( exception: e, stack: s, @@ -2200,7 +2134,7 @@ abstract class ElectrumWalletBase )); } }, onError: (e, s) { - printV("sub_listen error: $e $s"); + print("sub_listen error: $e $s"); }); })); } @@ -2221,6 +2155,18 @@ abstract class ElectrumWalletBase var totalConfirmed = 0; var totalUnconfirmed = 0; + unspentCoinsInfo.values.forEach((info) { + unspentCoins.forEach((element) { + if (element.hash == info.hash && + element.vout == info.vout && + info.isFrozen && + element.bitcoinAddressRecord.address == info.address && + element.value == info.value) { + totalFrozen += element.value; + } + }); + }); + if (hasSilentPaymentsScanning) { // Add values from unspent coins that are not fetched by the address list // i.e. scanned silent payments @@ -2236,26 +2182,11 @@ abstract class ElectrumWalletBase }); } - unspentCoinsInfo.values.forEach((info) { - unspentCoins.forEach((element) { - if (element.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) return; - - if (element.hash == info.hash && - element.vout == info.vout && - element.bitcoinAddressRecord.address == info.address && - element.value == info.value) { - if (info.isFrozen) { - totalFrozen += element.value; - } - } - }); - }); - final balances = await Future.wait(balanceFutures); if (balances.isNotEmpty && balances.first['confirmed'] == null) { // if we got null balance responses from the server, set our connection status to lost and return our last known balance: - printV("got null balance responses from the server, setting connection status to lost"); + print("got null balance responses from the server, setting connection status to lost"); syncStatus = LostConnectionSyncStatus(); return balance[currency] ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); } @@ -2282,7 +2213,7 @@ abstract class ElectrumWalletBase } Future updateBalance() async { - printV("updateBalance() called!"); + print("updateBalance() called!"); balance[currency] = await fetchBalances(); await save(); } @@ -2422,7 +2353,7 @@ abstract class ElectrumWalletBase } void _syncStatusReaction(SyncStatus syncStatus) async { - printV("SYNC_STATUS_CHANGE: ${syncStatus}"); + print("SYNC_STATUS_CHANGE: ${syncStatus}"); if (syncStatus is SyncingSyncStatus) { return; } @@ -2502,12 +2433,6 @@ abstract class ElectrumWalletBase transactionHistory.addOne(tx); } } - - @override - String formatCryptoAmount(String amount) { - final amountInt = int.parse(amount); - return bitcoinAmountToString(amount: amountInt); - } } class ScanNode { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 614a06a3b..c29579436 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -3,9 +3,6 @@ import 'dart:io' show Platform; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum_wallet.dart'; -import 'package:cw_core/unspent_coin_type.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; @@ -48,6 +45,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { List? initialMwebAddresses, Bip32Slip10Secp256k1? masterHd, BitcoinAddressType? initialAddressPageType, + }) : _addresses = ObservableList.of((initialAddresses ?? []).toSet()), addressesByReceiveType = ObservableList.of(([]).toSet()), @@ -144,32 +142,27 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return silentAddress.toString(); } - final typeMatchingAddresses = _addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList(); - final typeMatchingReceiveAddresses = typeMatchingAddresses.where((addr) => !addr.isUsed).toList(); + String receiveAddress; - if (!isEnabledAutoGenerateSubaddress) { - if (previousAddressRecord != null && - previousAddressRecord!.type == addressPageType) { - return previousAddressRecord!.address; + final typeMatchingReceiveAddresses = + receiveAddresses.where(_isAddressPageTypeMatch).where((addr) => !addr.isUsed); + + if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) || + typeMatchingReceiveAddresses.isEmpty) { + receiveAddress = generateNewAddress().address; + } else { + final previousAddressMatchesType = + previousAddressRecord != null && previousAddressRecord!.type == addressPageType; + + if (previousAddressMatchesType && + typeMatchingReceiveAddresses.first.address != addressesByReceiveType.first.address) { + receiveAddress = previousAddressRecord!.address; + } else { + receiveAddress = typeMatchingReceiveAddresses.first.address; } - - if (typeMatchingAddresses.isNotEmpty) { - return typeMatchingAddresses.first.address; - } - - return generateNewAddress().address; } - if (typeMatchingAddresses.isEmpty || typeMatchingReceiveAddresses.isEmpty) { - return generateNewAddress().address; - } - - final prev = previousAddressRecord; - if (prev != null && prev.type == addressPageType && !prev.isUsed) { - return prev.address; - } - - return typeMatchingReceiveAddresses.first.address; + return receiveAddress; } @observable @@ -192,15 +185,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return; } try { - final addressRecord = _addresses.firstWhere( - (addressRecord) => addressRecord.address == addr, - ); + final addressRecord = _addresses.firstWhere( + (addressRecord) => addressRecord.address == addr, + ); - previousAddressRecord = addressRecord; - receiveAddresses.remove(addressRecord); - receiveAddresses.insert(0, addressRecord); + previousAddressRecord = addressRecord; + receiveAddresses.remove(addressRecord); + receiveAddresses.insert(0, addressRecord); } catch (e) { - printV("ElectrumWalletAddressBase: set address ($addr): $e"); + print("ElectrumWalletAddressBase: set address ($addr): $e"); } } @@ -279,10 +272,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @action - Future getChangeAddress( - {List? inputs, - List? outputs, - UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) async { + Future getChangeAddress({List? inputs, List? outputs, bool isPegIn = false}) async { updateChangeAddresses(); if (changeAddresses.isEmpty) { @@ -357,10 +347,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { type: addressPageType, network: network, ); - Future.delayed(Duration.zero, () { - _addresses.add(address); - updateAddressesByMatch(); - }); + _addresses.add(address); + Future.delayed(Duration.zero, () => updateAddressesByMatch()); return address; } @@ -495,7 +483,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { await saveAddressesInBox(); } catch (e) { - printV("updateAddresses $e"); + print("updateAddresses $e"); } } diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 08c56c600..86228fc83 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:typed_data'; import 'package:convert/convert.dart' as convert; import 'dart:math'; @@ -8,8 +9,6 @@ import 'package:crypto/crypto.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/mweb_utxo.dart'; -import 'package:cw_core/unspent_coin_type.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/node.dart'; import 'package:cw_mweb/mwebd.pbgrpc.dart'; import 'package:fixnum/fixnum.dart'; @@ -76,7 +75,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { }) : super( mnemonic: mnemonic, password: password, - passphrase: passphrase, xpub: xpub, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, @@ -155,9 +153,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { @observable SyncStatus mwebSyncStatus = NotConnectedSyncStatus(); - @override - bool get hasRescan => true; - List get scanSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw; List get spendSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw; @@ -288,7 +283,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future waitForMwebAddresses() async { - printV("waitForMwebAddresses() called!"); + print("waitForMwebAddresses() called!"); // ensure that we have the full 1000 mweb addresses generated before continuing: // should no longer be needed, but leaving here just in case await (walletAddresses as LitecoinWalletAddresses).ensureMwebAddressUpToIndexExists(1020); @@ -307,8 +302,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { @action @override Future startSync() async { - printV("startSync() called!"); - printV("STARTING SYNC - MWEB ENABLED: $mwebEnabled"); + print("startSync() called!"); + print("STARTING SYNC - MWEB ENABLED: $mwebEnabled"); if (!mwebEnabled) { try { // in case we're switching from a litecoin wallet that had mweb enabled @@ -322,33 +317,33 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { return; } - printV("STARTING SYNC - MWEB ENABLED: $mwebEnabled"); + print("STARTING SYNC - MWEB ENABLED: $mwebEnabled"); _syncTimer?.cancel(); try { mwebSyncStatus = SyncronizingSyncStatus(); try { await subscribeForUpdates(); } catch (e) { - printV("failed to subscribe for updates: $e"); + print("failed to subcribe for updates: $e"); } updateFeeRates(); _feeRatesTimer?.cancel(); _feeRatesTimer = Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates()); - printV("START SYNC FUNCS"); + print("START SYNC FUNCS"); await waitForMwebAddresses(); await processMwebUtxos(); await updateTransactions(); await updateUnspent(); await updateBalance(); - } catch (e) { - printV("failed to start mweb sync: $e"); - syncStatus = FailedSyncStatus(); + print("DONE SYNC FUNCS"); + } catch (e, s) { + print("mweb sync failed: $e $s"); + mwebSyncStatus = FailedSyncStatus(error: "mweb sync failed: $e"); return; } - _syncTimer?.cancel(); _syncTimer = Timer.periodic(const Duration(milliseconds: 3000), (timer) async { if (mwebSyncStatus is FailedSyncStatus) { _syncTimer?.cancel(); @@ -398,6 +393,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { // if the confirmations haven't changed, skip updating: if (tx.confirmations == confirmations) continue; + // if an outgoing tx is now confirmed, delete the utxo from the box (delete the unspent coin): if (confirmations >= 2 && tx.direction == TransactionDirection.outgoing && @@ -405,7 +401,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { for (var coin in tx.unspents!) { final utxo = mwebUtxosBox.get(coin.address); if (utxo != null) { - printV("deleting utxo ${coin.address} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + print("deleting utxo ${coin.address} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); await mwebUtxosBox.delete(coin.address); } } @@ -432,7 +428,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { return; } } catch (e) { - printV("error syncing: $e"); + print("error syncing: $e"); mwebSyncStatus = FailedSyncStatus(error: e.toString()); } }); @@ -441,12 +437,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { @action @override Future stopSync() async { - printV("stopSync() called!"); + print("stopSync() called!"); _syncTimer?.cancel(); _utxoStream?.cancel(); _feeRatesTimer?.cancel(); await CwMweb.stop(); - printV("stopped syncing!"); + print("stopped syncing!"); } Future initMwebUtxosBox() async { @@ -464,9 +460,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { final oldBox = await CakeHive.openBox(oldBoxName); mwebUtxosBox = await CakeHive.openBox(newBoxName); for (final key in oldBox.keys) { - final value = oldBox.get(key); - await oldBox.delete(key); - await mwebUtxosBox.put(key, value!); + await mwebUtxosBox.put(key, oldBox.get(key)!); } oldBox.deleteFromDisk(); @@ -520,7 +514,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future handleIncoming(MwebUtxo utxo) async { - printV("handleIncoming() called!"); + print("handleIncoming() called!"); final status = await CwMweb.status(StatusRequest()); var date = DateTime.now(); var confirmations = 0; @@ -565,7 +559,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { final addressRecord = walletAddresses.allAddresses .firstWhereOrNull((addressRecord) => addressRecord.address == utxo.address); if (addressRecord == null) { - printV("we don't have this address in the wallet! ${utxo.address}"); + print("we don't have this address in the wallet! ${utxo.address}"); return; } @@ -586,13 +580,13 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future processMwebUtxos() async { - printV("processMwebUtxos() called!"); + print("processMwebUtxos() called!"); if (!mwebEnabled) { return; } int restoreHeight = walletInfo.restoreHeight; - printV("SCANNING FROM HEIGHT: $restoreHeight"); + print("SCANNING FROM HEIGHT: $restoreHeight"); final req = UtxosRequest(scanSecret: scanSecret, fromHeight: restoreHeight); // process new utxos as they come in: @@ -603,7 +597,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } _utxoStream = responseStream.listen( (Utxo sUtxo) async { - // we're processing utxos, so our balance could still be inaccurate: + // we're processing utxos, so our balance could still be innacurate: if (mwebSyncStatus is! SyncronizingSyncStatus && mwebSyncStatus is! SyncingSyncStatus) { mwebSyncStatus = SyncronizingSyncStatus(); processingUtxos = true; @@ -627,7 +621,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { // but do update the utxo height if it's somehow different: final existingUtxo = mwebUtxosBox.get(utxo.outputId); if (existingUtxo!.height != utxo.height) { - printV( + print( "updating utxo height for $utxo.outputId: ${existingUtxo.height} -> ${utxo.height}"); existingUtxo.height = utxo.height; await mwebUtxosBox.put(utxo.outputId, existingUtxo); @@ -650,7 +644,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { await handleIncoming(utxo); }, onError: (error) { - printV("error in utxo stream: $error"); + print("error in utxo stream: $error"); mwebSyncStatus = FailedSyncStatus(error: error.toString()); }, cancelOnError: true, @@ -658,7 +652,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future deleteSpentUtxos() async { - printV("deleteSpentUtxos() called!"); + print("deleteSpentUtxos() called!"); final chainHeight = await electrumClient.getCurrentBlockChainTip(); final status = await CwMweb.status(StatusRequest()); if (chainHeight == null || status.blockHeaderHeight != chainHeight) return; @@ -682,7 +676,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future checkMwebUtxosSpent() async { - printV("checkMwebUtxosSpent() called!"); + print("checkMwebUtxosSpent() called!"); if (!mwebEnabled) { return; } @@ -763,13 +757,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { if (!mwebEnabled) return false; if (!tx.isPending) return false; - final isMwebTx = (tx.inputAddresses?.any((addr) => addr.contains("mweb")) ?? false) || - (tx.outputAddresses?.any((addr) => addr.contains("mweb")) ?? false); - - if (!isMwebTx) { - return false; - } - final outputId = [], target = {}; final isHash = RegExp(r'^[a-f0-9]{64}$').hasMatch; final spendingOutputIds = tx.inputAddresses?.where(isHash) ?? []; @@ -804,7 +791,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future updateUnspent() async { - printV("updateUnspent() called!"); + print("updateUnspent() called!"); await checkMwebUtxosSpent(); await updateAllUnspents(); } @@ -835,7 +822,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { .firstWhereOrNull((addressRecord) => addressRecord.address == utxo.address); if (addressRecord == null) { - printV("utxo contains an address that is not in the wallet: ${utxo.address}"); + print("utxo contains an address that is not in the wallet: ${utxo.address}"); return; } final unspent = BitcoinUnspent( @@ -876,7 +863,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { mwebUtxosBox.values.forEach((utxo) { bool isConfirmed = utxo.height > 0; - printV( + print( "utxo: ${isConfirmed ? "confirmed" : "unconfirmed"} ${utxo.spent ? "spent" : "unspent"} ${utxo.outputId} ${utxo.height} ${utxo.value}"); if (isConfirmed) { @@ -971,19 +958,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { List? inputPrivKeyInfos, List? vinOutpoints, }) async { - bool spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddresType.mweb); - bool paysToMweb = outputs + final spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddresType.mweb); + final paysToMweb = outputs .any((output) => output.toOutput.scriptPubKey.getAddressType() == SegwitAddresType.mweb); - - bool isRegular = !spendsMweb && !paysToMweb; - bool isMweb = spendsMweb || paysToMweb; - - if (isMweb && !mwebEnabled) { - throw Exception("MWEB is not enabled! can't calculate fee without starting the mweb server!"); - // TODO: likely the change address is mweb and just not updated - } - - if (isRegular) { + if (!spendsMweb && !paysToMweb) { return await super.calcFee( utxos: utxos, outputs: outputs, @@ -995,6 +973,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { ); } + if (!mwebEnabled) { + throw Exception("MWEB is not enabled! can't calculate fee without starting the mweb server!"); + } + if (outputs.length == 1 && outputs[0].toOutput.amount == BigInt.zero) { outputs = [ BitcoinScriptOutput( @@ -1019,7 +1001,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { final sum1 = _sumOutputAmounts(outputs.map((e) => e.toOutput).toList()) + fee; final sum2 = utxos.sumOfUtxosValue(); if (sum1 != sum2) { - printV("@@@@@ WE HAD TO ADJUST THE FEE! @@@@@@@@"); + print("@@@@@ WE HAD TO ADJUST THE FEE! @@@@@@@@"); final diff = sum2 - sum1; // add the difference to the fee (abs value): fee += diff.abs(); @@ -1065,7 +1047,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { if (!mwebEnabled) { tx.changeAddressOverride = - (await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(coinTypeToSpendFrom: UnspentCoinType.nonMweb)) + (await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(isPegIn: false)) .address; return tx; } @@ -1113,15 +1095,13 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } } - // could probably be simplified but left for clarity: bool isPegIn = !hasMwebInput && hasMwebOutput; bool isPegOut = hasMwebInput && hasRegularOutput; bool isRegular = !hasMwebInput && !hasMwebOutput; - bool shouldNotUseMwebChange = isPegIn || isRegular || !hasMwebInput; tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses) - .getChangeAddress(coinTypeToSpendFrom: shouldNotUseMwebChange ? UnspentCoinType.nonMweb : UnspentCoinType.any)) + .getChangeAddress(isPegIn: isPegIn || isRegular)) .address; - if (isRegular) { + if (!hasMwebInput && !hasMwebOutput) { tx.isMweb = false; return tx; } @@ -1186,7 +1166,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { addressRecord.balance -= utxo.value.toInt(); }); transaction.inputAddresses?.addAll(addresses); - printV("isPegIn: $isPegIn, isPegOut: $isPegOut"); + print("isPegIn: $isPegIn, isPegOut: $isPegOut"); transaction.additionalInfo["isPegIn"] = isPegIn; transaction.additionalInfo["isPegOut"] = isPegOut; transactionHistory.addOne(transaction); @@ -1194,10 +1174,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { await updateBalance(); }); } catch (e, s) { - printV(e); - printV(s); + print(e); + print(s); if (e.toString().contains("commit failed")) { - printV(e); + print(e); throw Exception("Transaction commit failed (no peers responded), please try again."); } rethrow; @@ -1210,7 +1190,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } @override - Future close({bool shouldCleanup = false}) async { + Future close({required bool shouldCleanup}) async { _utxoStream?.cancel(); _feeRatesTimer?.cancel(); _syncTimer?.cancel(); @@ -1224,9 +1204,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } Future setMwebEnabled(bool enabled) async { - if (mwebEnabled == enabled && - alwaysScan == enabled && - (walletAddresses as LitecoinWalletAddresses).mwebEnabled == enabled) { + if (mwebEnabled == enabled) { return; } diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index bbb987766..062c590ba 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -9,8 +9,6 @@ import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/utils.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:cw_core/unspent_coin_type.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_mweb/cw_mweb.dart'; import 'package:flutter/foundation.dart'; @@ -37,7 +35,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with for (int i = 0; i < mwebAddresses.length; i++) { mwebAddrs.add(mwebAddresses[i].address); } - printV("initialized with ${mwebAddrs.length} mweb addresses"); + print("initialized with ${mwebAddrs.length} mweb addresses"); } final Bip32Slip10Secp256k1? mwebHd; @@ -75,25 +73,25 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with } while (generating) { - printV("generating....."); + print("generating....."); // this function was called multiple times in multiple places: await Future.delayed(const Duration(milliseconds: 100)); } - printV("Generating MWEB addresses up to index $index"); + print("Generating MWEB addresses up to index $index"); generating = true; try { while (mwebAddrs.length <= (index + 1)) { final addresses = await CwMweb.addresses(scan, spend, mwebAddrs.length, mwebAddrs.length + 50); - printV("generated up to index ${mwebAddrs.length}"); + print("generated up to index ${mwebAddrs.length}"); // sleep for a bit to avoid making the main thread unresponsive: await Future.delayed(Duration(milliseconds: 200)); mwebAddrs.addAll(addresses!); } } catch (_) {} generating = false; - printV("Done generating MWEB addresses len: ${mwebAddrs.length}"); + print("Done generating MWEB addresses len: ${mwebAddrs.length}"); // ensure mweb addresses are up to date: // This is the Case if the Litecoin Wallet is a hardware Wallet @@ -111,7 +109,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with )) .toList(); addMwebAddresses(addressRecords); - printV("set ${addressRecords.length} mweb addresses"); + print("set ${addressRecords.length} mweb addresses"); } } @@ -149,12 +147,10 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with @action @override Future getChangeAddress( - {List? inputs, - List? outputs, - UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) async { + {List? inputs, List? outputs, bool isPegIn = false}) async { // use regular change address on peg in, otherwise use mweb for change address: - if (!mwebEnabled || coinTypeToSpendFrom == UnspentCoinType.nonMweb) { + if (!mwebEnabled || isPegIn) { return super.getChangeAddress(); } @@ -181,17 +177,19 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with }); bool isPegIn = !comesFromMweb && outputsToMweb; - bool isNonMweb = !comesFromMweb && !outputsToMweb; - // use regular change address if it's not an mweb tx or if it's a peg in: - if (isPegIn || isNonMweb) { + if (isPegIn && mwebEnabled) { + return super.getChangeAddress(); + } + + // use regular change address if it's not an mweb tx: + if (!comesFromMweb && !outputsToMweb) { return super.getChangeAddress(); } } if (mwebEnabled) { await ensureMwebAddressUpToIndexExists(1); - updateChangeAddresses(); return BitcoinAddressRecord( mwebAddrs[0], index: 0, diff --git a/cw_bitcoin/lib/payjoin/manager.dart b/cw_bitcoin/lib/payjoin/manager.dart deleted file mode 100644 index 95a523d89..000000000 --- a/cw_bitcoin/lib/payjoin/manager.dart +++ /dev/null @@ -1,310 +0,0 @@ -import 'dart:async'; -import 'dart:isolate'; -import 'dart:math'; -import 'dart:typed_data'; - -import 'package:bitcoin_base/bitcoin_base.dart'; -import 'package:cw_bitcoin/bitcoin_wallet.dart'; -import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart'; -import 'package:cw_bitcoin/payjoin/payjoin_persister.dart'; -import 'package:cw_bitcoin/payjoin/payjoin_receive_worker.dart'; -import 'package:cw_bitcoin/payjoin/payjoin_send_worker.dart'; -import 'package:cw_bitcoin/payjoin/payjoin_session_errors.dart'; -import 'package:cw_bitcoin/payjoin/storage.dart'; -import 'package:cw_bitcoin/psbt/signer.dart'; -import 'package:cw_bitcoin/psbt/utils.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:payjoin_flutter/common.dart'; -import 'package:payjoin_flutter/receive.dart'; -import 'package:payjoin_flutter/send.dart'; -import 'package:payjoin_flutter/src/config.dart' as pj_config; -import 'package:payjoin_flutter/uri.dart' as PayjoinUri; - -class PayjoinManager { - PayjoinManager(this._payjoinStorage, this._wallet); - - final PayjoinStorage _payjoinStorage; - final BitcoinWalletBase _wallet; - final Map _activePollers = {}; - - static const List ohttpRelayUrls = [ - 'https://pj.bobspacebkk.com', - 'https://ohttp.achow101.com', - 'https://ohttp.cakewallet.com', - ]; - - static String randomOhttpRelayUrl() => - ohttpRelayUrls[Random.secure().nextInt(ohttpRelayUrls.length)]; - - static const payjoinDirectoryUrl = 'https://payjo.in'; - - Future initPayjoin() => pj_config.PConfig.initializeApp(); - - Future resumeSessions() async { - final allSessions = _payjoinStorage.readAllOpenSessions(_wallet.id); - - final spawnedSessions = allSessions.map((session) { - if (session.isSenderSession) { - printV("Resuming Payjoin Sender Session ${session.pjUri!}"); - return _spawnSender( - sender: Sender.fromJson(json: session.sender!), - pjUri: session.pjUri!, - ); - } - final receiver = Receiver.fromJson(json: session.receiver!); - printV("Resuming Payjoin Receiver Session ${receiver.id()}"); - return spawnReceiver(receiver: receiver); - }); - - printV("Resumed ${spawnedSessions.length} Payjoin Sessions"); - await Future.wait(spawnedSessions); - } - - Future initSender( - String pjUriString, String originalPsbt, int networkFeesSatPerVb) async { - try { - final pjUri = - (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported(); - final minFeeRateSatPerKwu = BigInt.from(networkFeesSatPerVb * 250); - final senderBuilder = await SenderBuilder.fromPsbtAndUri( - psbtBase64: originalPsbt, - pjUri: pjUri, - ); - final persister = PayjoinSenderPersister.impl(); - final newSender = - await senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu); - final senderToken = await newSender.persist(persister: persister); - - return Sender.load(token: senderToken, persister: persister); - } catch (e) { - throw Exception('Error initializing Payjoin Sender: $e'); - } - } - - Future spawnNewSender({ - required Sender sender, - required String pjUrl, - required BigInt amount, - bool isTestnet = false, - }) async { - final pjUri = Uri.parse(pjUrl).queryParameters['pj']!; - await _payjoinStorage.insertSenderSession( - sender, pjUri, _wallet.id, amount); - - return _spawnSender(isTestnet: isTestnet, sender: sender, pjUri: pjUri); - } - - Future _spawnSender({ - required Sender sender, - required String pjUri, - bool isTestnet = false, - }) async { - final completer = Completer(); - final receivePort = ReceivePort(); - - receivePort.listen((message) async { - if (message is Map) { - try { - switch (message['type'] as PayjoinSenderRequestTypes) { - case PayjoinSenderRequestTypes.requestPosted: - return; - case PayjoinSenderRequestTypes.psbtToSign: - final proposalPsbt = message['psbt'] as String; - final utxos = _wallet.getUtxoWithPrivateKeys(); - final finalizedPsbt = await _wallet.signPsbt(proposalPsbt, utxos); - final txId = getTxIdFromPsbtV0(finalizedPsbt); - _wallet.commitPsbt(finalizedPsbt); - - _cleanupSession(pjUri); - await _payjoinStorage.markSenderSessionComplete(pjUri, txId); - completer.complete(); - } - } catch (e) { - _cleanupSession(pjUri); - await _payjoinStorage.markSenderSessionUnrecoverable(pjUri, e.toString()); - completer.complete(); - } - } else if (message is PayjoinSessionError) { - _cleanupSession(pjUri); - if (message is UnrecoverableError) { - await _payjoinStorage.markSenderSessionUnrecoverable(pjUri, message.message); - completer.complete(); - } else if (message is RecoverableError) { - completer.complete(); - } else { - completer.completeError(message); - } - } - }); - - final isolate = await Isolate.spawn( - PayjoinSenderWorker.run, - [receivePort.sendPort, sender.toJson(), pjUri], - ); - - _activePollers[pjUri] = PayjoinPollerSession(isolate, receivePort); - - return completer.future; - } - - Future getUnusedReceiver(String address, - [bool isTestnet = false]) async { - final session = _payjoinStorage.getUnusedActiveReceiverSession(_wallet.id); - - if (session != null) { - await PayjoinUri.Url.fromStr(payjoinDirectoryUrl); - - return Receiver.fromJson(json: session.receiver!); - } - - return initReceiver(address); - } - - Future initReceiver(String address, [bool isTestnet = false]) async { - final ohttpKeys = await PayjoinUri.fetchOhttpKeys( - ohttpRelay: await randomOhttpRelayUrl(), - payjoinDirectory: payjoinDirectoryUrl, - ); - - final newReceiver = await NewReceiver.create( - address: address, - network: isTestnet ? Network.testnet : Network.bitcoin, - directory: payjoinDirectoryUrl, - ohttpKeys: ohttpKeys, - ); - final persister = PayjoinReceiverPersister.impl(); - final receiverToken = await newReceiver.persist(persister: persister); - final receiver = await Receiver.load(persister: persister, token: receiverToken); - - await _payjoinStorage.insertReceiverSession(receiver, _wallet.id); - - return receiver; - } - - Future spawnReceiver({ - required Receiver receiver, - bool isTestnet = false, - }) async { - final completer = Completer(); - final receivePort = ReceivePort(); - - SendPort? mainToIsolateSendPort; - List utxos = []; - String rawAmount = '0'; - - receivePort.listen((message) async { - if (message is Map) { - try { - switch (message['type'] as PayjoinReceiverRequestTypes) { - case PayjoinReceiverRequestTypes.processOriginalTx: - final tx = message['tx'] as String; - rawAmount = getOutputAmountFromTx(tx, _wallet); - break; - case PayjoinReceiverRequestTypes.checkIsOwned: - (_wallet.walletAddresses as BitcoinWalletAddresses) - .newPayjoinReceiver(); - _payjoinStorage.markReceiverSessionInProgress(receiver.id()); - - final inputScript = message['input_script'] as Uint8List; - final isOwned = - _wallet.isMine(Script.fromRaw(byteData: inputScript)); - mainToIsolateSendPort?.send({ - 'requestId': message['requestId'], - 'result': isOwned, - }); - break; - - case PayjoinReceiverRequestTypes.checkIsReceiverOutput: - final outputScript = message['output_script'] as Uint8List; - final isReceiverOutput = - _wallet.isMine(Script.fromRaw(byteData: outputScript)); - mainToIsolateSendPort?.send({ - 'requestId': message['requestId'], - 'result': isReceiverOutput, - }); - break; - - case PayjoinReceiverRequestTypes.getCandidateInputs: - utxos = _wallet.getUtxoWithPrivateKeys(); - if (utxos.isEmpty) { - await _wallet.updateAllUnspents(); - utxos = _wallet.getUtxoWithPrivateKeys(); - } - mainToIsolateSendPort?.send({ - 'requestId': message['requestId'], - 'result': utxos, - }); - break; - - case PayjoinReceiverRequestTypes.processPsbt: - final psbt = message['psbt'] as String; - final signedPsbt = await _wallet.signPsbt(psbt, utxos); - mainToIsolateSendPort?.send({ - 'requestId': message['requestId'], - 'result': signedPsbt, - }); - break; - - case PayjoinReceiverRequestTypes.proposalSent: - _cleanupSession(receiver.id()); - final psbt = message['psbt'] as String; - await _payjoinStorage.markReceiverSessionComplete( - receiver.id(), getTxIdFromPsbtV0(psbt), rawAmount); - completer.complete(); - } - } catch (e) { - _cleanupSession(receiver.id()); - await _payjoinStorage.markReceiverSessionUnrecoverable( - receiver.id(), e.toString()); - completer.completeError(e); - } - } else if (message is PayjoinSessionError) { - _cleanupSession(receiver.id()); - if (message is UnrecoverableError) { - await _payjoinStorage.markReceiverSessionUnrecoverable( - receiver.id(), message.message); - completer.complete(); - } else if (message is RecoverableError) { - completer.complete(); - } else { - completer.completeError(message); - } - } else if (message is SendPort) { - mainToIsolateSendPort = message; - } - }); - - final isolate = await Isolate.spawn( - PayjoinReceiverWorker.run, - [receivePort.sendPort, receiver.toJson()], - ); - - _activePollers[receiver.id()] = PayjoinPollerSession(isolate, receivePort); - - return completer.future; - } - - void cleanupSessions() { - final sessionIds = _activePollers.keys.toList(); - for (final sessionId in sessionIds) { - _cleanupSession(sessionId); - } - } - - void _cleanupSession(String sessionId) { - _activePollers[sessionId]?.close(); - _activePollers.remove(sessionId); - } -} - -class PayjoinPollerSession { - final Isolate isolate; - final ReceivePort port; - - PayjoinPollerSession(this.isolate, this.port); - - void close() { - isolate.kill(); - port.close(); - } -} diff --git a/cw_bitcoin/lib/payjoin/payjoin_persister.dart b/cw_bitcoin/lib/payjoin/payjoin_persister.dart deleted file mode 100644 index 4e395e36a..000000000 --- a/cw_bitcoin/lib/payjoin/payjoin_persister.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:payjoin_flutter/src/generated/api/receive.dart'; -import 'package:payjoin_flutter/src/generated/api/send.dart'; - -class PayjoinSenderPersister implements DartSenderPersister { - static DartSenderPersister impl() { - final impl = PayjoinSenderPersister(); - return DartSenderPersister( - save: (sender) => impl.save(sender: sender), - load: (token) => impl.load(token: token), - ); - } - - final Map _store = {}; - - Future save({required FfiSender sender}) async { - final token = sender.key(); - _store[token.toBytes().toString()] = sender; - return token; - } - - Future load({required SenderToken token}) async { - final sender = _store[token.toBytes().toString()]; - if (sender == null) { - throw Exception('Sender not found for the provided token.'); - } - return sender; - } - - @override - void dispose() => _store.clear(); - - @override - bool get isDisposed => _store.isEmpty; -} - -class PayjoinReceiverPersister implements DartReceiverPersister { - static DartReceiverPersister impl() { - final impl = PayjoinReceiverPersister(); - return DartReceiverPersister( - save: (receiver) => impl.save(receiver: receiver), - load: (token) => impl.load(token: token), - ); - } - - final Map _store = {}; - - Future save({required FfiReceiver receiver}) async { - final token = receiver.key(); - _store[token.toBytes().toString()] = receiver; - return token; - } - - Future load({required ReceiverToken token}) async { - final receiver = _store[token.toBytes().toString()]; - if (receiver == null) { - throw Exception('Receiver not found for the provided token.'); - } - return receiver; - } - - @override - void dispose() => _store.clear(); - - @override - bool get isDisposed => _store.isEmpty; -} diff --git a/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart b/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart deleted file mode 100644 index c56148de2..000000000 --- a/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart +++ /dev/null @@ -1,222 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'dart:isolate'; -import 'dart:typed_data'; - -import 'package:blockchain_utils/blockchain_utils.dart'; -import 'package:cw_bitcoin/payjoin/manager.dart'; -import 'package:cw_bitcoin/payjoin/payjoin_session_errors.dart'; -import 'package:cw_bitcoin/psbt/signer.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; -import 'package:payjoin_flutter/bitcoin_ffi.dart'; -import 'package:payjoin_flutter/common.dart'; -import 'package:payjoin_flutter/receive.dart'; -import 'package:payjoin_flutter/src/generated/frb_generated.dart' as pj; -import 'package:http/http.dart' as very_insecure_http_do_not_use; // for errors - -enum PayjoinReceiverRequestTypes { - processOriginalTx, - proposalSent, - getCandidateInputs, - checkIsOwned, - checkIsReceiverOutput, - processPsbt; -} - -class PayjoinReceiverWorker { - final SendPort sendPort; - final pendingRequests = >{}; - - PayjoinReceiverWorker._(this.sendPort); - static final client = ProxyWrapper().getHttpIOClient(); - static Future run(List args) async { - await pj.core.init(); - - final sendPort = args[0] as SendPort; - final receiverJson = args[1] as String; - - final worker = PayjoinReceiverWorker._(sendPort); - final receivePort = ReceivePort(); - - sendPort.send(receivePort.sendPort); - receivePort.listen(worker.handleMessage); - - try { - final receiver = Receiver.fromJson(json: receiverJson); - - final uncheckedProposal = - await worker.receiveUncheckedProposal(receiver); - - final originalTx = await uncheckedProposal.extractTxToScheduleBroadcast(); - sendPort.send({ - 'type': PayjoinReceiverRequestTypes.processOriginalTx, - 'tx': BytesUtils.toHexString(originalTx), - }); - - final payjoinProposal = await worker.processPayjoinProposal( - uncheckedProposal, - ); - final psbt = await worker.sendFinalProposal(payjoinProposal); - sendPort.send({ - 'type': PayjoinReceiverRequestTypes.proposalSent, - 'psbt': psbt, - }); - } catch (e) { - if (e is HttpException || - (e is very_insecure_http_do_not_use.ClientException && - e.message.contains("Software caused connection abort"))) { - sendPort.send(PayjoinSessionError.recoverable(e.toString())); - } else { - sendPort.send(PayjoinSessionError.unrecoverable(e.toString())); - } - } - } - - void handleMessage(dynamic message) async { - if (message is Map) { - final requestId = message['requestId'] as String?; - if (requestId != null && pendingRequests.containsKey(requestId)) { - pendingRequests[requestId]!.complete(message['result']); - pendingRequests.remove(requestId); - } - } - } - - Future _sendRequest(PayjoinReceiverRequestTypes type, - [Map data = const {}]) async { - final completer = Completer(); - final requestId = DateTime.now().millisecondsSinceEpoch.toString(); - pendingRequests[requestId] = completer; - - sendPort.send({ - ...data, - 'type': type, - 'requestId': requestId, - }); - - return completer.future; - } - - Future receiveUncheckedProposal(Receiver session) async { - while (true) { - printV("Polling for Proposal (${session.id()})"); - final extractReq = await session.extractReq( - ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(), - ); - final request = extractReq.$1; - - final url = Uri.parse(request.url.asString()); - final httpRequest = await client.post(url, - headers: {'Content-Type': request.contentType}, body: request.body); - - final proposal = await session.processRes( - body: httpRequest.bodyBytes, ctx: extractReq.$2); - if (proposal != null) return proposal; - } - } - - Future sendFinalProposal(PayjoinProposal finalProposal) async { - final req = await finalProposal.extractReq( - ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(), - ); - final proposalReq = req.$1; - final proposalCtx = req.$2; - - final request = await client.post( - Uri.parse(proposalReq.url.asString()), - headers: {"Content-Type": proposalReq.contentType}, - body: proposalReq.body, - ); - - await finalProposal.processRes( - res: request.bodyBytes, - ohttpContext: proposalCtx, - ); - - return await finalProposal.psbt(); - } - - Future processPayjoinProposal( - UncheckedProposal proposal) async { - await proposal.extractTxToScheduleBroadcast(); - // TODO Handle this. send to the main port on a timer? - - try { - // Receive Check 1: can broadcast - final pj1 = await proposal.assumeInteractiveReceiver(); - - // Receive Check 2: original PSBT has no receiver-owned inputs - final pj2 = await pj1.checkInputsNotOwned( - isOwned: (inputScript) async { - final result = await _sendRequest( - PayjoinReceiverRequestTypes.checkIsOwned, - {'input_script': inputScript}, - ); - return result as bool; - }, - ); - // Receive Check 3: sender inputs have not been seen before (prevent probing attacks) - final pj3 = await pj2.checkNoInputsSeenBefore(isKnown: (input) => false); - - // Identify receiver outputs - final pj4 = await pj3.identifyReceiverOutputs( - isReceiverOutput: (outputScript) async { - final result = await _sendRequest( - PayjoinReceiverRequestTypes.checkIsReceiverOutput, - {'output_script': outputScript}, - ); - return result as bool; - }, - ); - final pj5 = await pj4.commitOutputs(); - - final listUnspent = - await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs); - final unspent = listUnspent as List; - if (unspent.isEmpty) throw RecoverableError('No unspent outputs available'); - - final selectedUtxo = await _inputPairFromUtxo(unspent[0]); - final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]); - final pj7 = await pj6.commitInputs(); - - // Finalize proposal - final payjoinProposal = await pj7.finalizeProposal( - processPsbt: (String psbt) async { - final result = await _sendRequest( - PayjoinReceiverRequestTypes.processPsbt, {'psbt': psbt}); - return result as String; - }, - // TODO set maxFeeRateSatPerVb - maxFeeRateSatPerVb: BigInt.from(10000), - ); - return payjoinProposal; - } catch (e) { - printV('Error occurred while finalizing proposal: $e'); - rethrow; - } - } - - Future _inputPairFromUtxo(UtxoWithPrivateKey utxo) async { - final txout = TxOut( - value: utxo.utxo.value, - scriptPubkey: Uint8List.fromList( - utxo.ownerDetails.address.toScriptPubKey().toBytes()), - ); - - final psbtin = - PsbtInput(witnessUtxo: txout, redeemScript: null, witnessScript: null); - - final previousOutput = - OutPoint(txid: utxo.utxo.txHash, vout: utxo.utxo.vout); - - final txin = TxIn( - previousOutput: previousOutput, - scriptSig: await Script.newInstance(rawOutputScript: []), - witness: [], - sequence: 0, - ); - - return InputPair.newInstance(txin: txin, psbtin: psbtin); - } -} diff --git a/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart b/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart deleted file mode 100644 index 7e85cc773..000000000 --- a/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'dart:isolate'; - -import 'package:cw_bitcoin/payjoin/manager.dart'; -import 'package:cw_bitcoin/payjoin/payjoin_session_errors.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; -import 'package:payjoin_flutter/common.dart'; -import 'package:payjoin_flutter/send.dart'; -import 'package:payjoin_flutter/src/generated/frb_generated.dart' as pj; -import 'package:payjoin_flutter/src/generated/api/send/error.dart' as pj_error; -import 'package:payjoin_flutter/uri.dart' as pj_uri; - -enum PayjoinSenderRequestTypes { - requestPosted, - psbtToSign; -} - -class PayjoinSenderWorker { - final SendPort sendPort; - final pendingRequests = >{}; - final String pjUrl; - - PayjoinSenderWorker._(this.sendPort, this.pjUrl); - - static Future run(List args) async { - await pj.core.init(); - - final sendPort = args[0] as SendPort; - final senderJson = args[1] as String; - final pjUrl = args[2] as String; - - final sender = Sender.fromJson(json: senderJson); - final worker = PayjoinSenderWorker._(sendPort, pjUrl); - - try { - final proposalPsbt = await worker.runSender(sender); - sendPort.send({ - 'type': PayjoinSenderRequestTypes.psbtToSign, - 'psbt': proposalPsbt, - }); - } catch (e) { - sendPort.send(e); - } - } - final client = ProxyWrapper().getHttpIOClient(); - - /// Run a payjoin sender (V2 protocol first, fallback to V1). - Future runSender(Sender sender) async { - - try { - return await _runSenderV2(sender); - } catch (e) { - printV(e); - if (e is pj_error.FfiCreateRequestError) { - return await _runSenderV1(sender); - } else if (e is HttpException) { - printV(e); - throw Exception(PayjoinSessionError.recoverable(e.toString())); - } else { - throw Exception(PayjoinSessionError.unrecoverable(e.toString())); - } - } - } - - /// Attempt to send payjoin using the V2 of the protocol. - Future _runSenderV2(Sender sender) async { - try { - final postRequest = await sender.extractV2( - ohttpProxyUrl: - await pj_uri.Url.fromStr(PayjoinManager.randomOhttpRelayUrl()), - ); - - final postResult = await _postRequest(postRequest.$1); - final getContext = - await postRequest.$2.processResponse(response: postResult); - - sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted, "pj": pjUrl}); - - while (true) { - printV('Polling V2 Proposal Request (${pjUrl})'); - - final getRequest = await getContext.extractReq( - ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(), - ); - final getRes = await _postRequest(getRequest.$1); - final proposalPsbt = await getContext.processResponse( - response: getRes, - ohttpCtx: getRequest.$2, - ); - printV("$proposalPsbt"); - if (proposalPsbt != null) return proposalPsbt; - } - } catch (e) { - rethrow; - } - } - - /// Attempt to send payjoin using the V1 of the protocol. - Future _runSenderV1(Sender sender) async { - try { - final postRequest = await sender.extractV1(); - final response = await _postRequest(postRequest.$1); - - sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted}); - - return await postRequest.$2.processResponse(response: response); - } catch (e, stack) { - throw PayjoinSessionError.unrecoverable('Send V1 payjoin error: $e, $stack'); - } - } - - Future> _postRequest(Request req) async { - final httpRequest = await client.post(Uri.parse(req.url.asString()), - headers: {'Content-Type': req.contentType}, body: req.body); - - return httpRequest.bodyBytes; - } -} diff --git a/cw_bitcoin/lib/payjoin/payjoin_session_errors.dart b/cw_bitcoin/lib/payjoin/payjoin_session_errors.dart deleted file mode 100644 index 06e0a5431..000000000 --- a/cw_bitcoin/lib/payjoin/payjoin_session_errors.dart +++ /dev/null @@ -1,16 +0,0 @@ -class PayjoinSessionError { - final String message; - - const PayjoinSessionError._(this.message); - - factory PayjoinSessionError.recoverable(String message) = RecoverableError; - factory PayjoinSessionError.unrecoverable(String message) = UnrecoverableError; -} - -class RecoverableError extends PayjoinSessionError { - const RecoverableError(super.message) : super._(); -} - -class UnrecoverableError extends PayjoinSessionError { - const UnrecoverableError(super.message) : super._(); -} diff --git a/cw_bitcoin/lib/payjoin/storage.dart b/cw_bitcoin/lib/payjoin/storage.dart deleted file mode 100644 index 5fb9d5716..000000000 --- a/cw_bitcoin/lib/payjoin/storage.dart +++ /dev/null @@ -1,104 +0,0 @@ -import 'package:cw_core/payjoin_session.dart'; -import 'package:hive/hive.dart'; -import 'package:payjoin_flutter/receive.dart'; -import 'package:payjoin_flutter/send.dart'; - -class PayjoinStorage { - PayjoinStorage(this._payjoinSessionSources); - - final Box _payjoinSessionSources; - - static const String _receiverPrefix = 'pj_recv_'; - static const String _senderPrefix = 'pj_send_'; - - Future insertReceiverSession( - Receiver receiver, - String walletId, - ) => - _payjoinSessionSources.put( - "$_receiverPrefix${receiver.id()}", - PayjoinSession( - walletId: walletId, - receiver: receiver.toJson(), - ), - ); - - PayjoinSession? getUnusedActiveReceiverSession(String walletId) => - _payjoinSessionSources.values - .where((session) => - session.walletId == walletId && - session.status == PayjoinSessionStatus.created.name && - !session.isSenderSession) - .firstOrNull; - - Future markReceiverSessionComplete( - String sessionId, String txId, String amount) async { - final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!; - - session.status = PayjoinSessionStatus.success.name; - session.txId = txId; - session.rawAmount = amount; - await session.save(); - } - - Future markReceiverSessionUnrecoverable( - String sessionId, String reason) async { - final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!; - - session.status = PayjoinSessionStatus.unrecoverable.name; - session.error = reason; - await session.save(); - } - - Future markReceiverSessionInProgress(String sessionId) async { - final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!; - - session.status = PayjoinSessionStatus.inProgress.name; - session.inProgressSince = DateTime.now(); - await session.save(); - } - - Future insertSenderSession( - Sender sender, - String pjUrl, - String walletId, - BigInt amount, - ) => - _payjoinSessionSources.put( - "$_senderPrefix$pjUrl", - PayjoinSession( - walletId: walletId, - pjUri: pjUrl, - sender: sender.toJson(), - status: PayjoinSessionStatus.inProgress.name, - inProgressSince: DateTime.now(), - rawAmount: amount.toString(), - ), - ); - - Future markSenderSessionComplete(String pjUrl, String txId) async { - final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!; - - session.status = PayjoinSessionStatus.success.name; - session.txId = txId; - await session.save(); - } - - Future markSenderSessionUnrecoverable(String pjUrl, String reason) async { - final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!; - - session.status = PayjoinSessionStatus.unrecoverable.name; - session.error = reason; - await session.save(); - } - - List readAllOpenSessions(String walletId) => - _payjoinSessionSources.values - .where((session) => - session.walletId == walletId && - ![ - PayjoinSessionStatus.success.name, - PayjoinSessionStatus.unrecoverable.name - ].contains(session.status)) - .toList(); -} diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index 6930524eb..411c7de16 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -1,4 +1,3 @@ -import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:grpc/grpc.dart'; import 'package:cw_bitcoin/exceptions.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; @@ -26,8 +25,6 @@ class PendingBitcoinTransaction with PendingTransaction { this.hasTaprootInputs = false, this.isMweb = false, this.utxos = const [], - this.publicKeys, - this.commitOverride, }) : _listeners = []; final WalletType type; @@ -46,8 +43,6 @@ class PendingBitcoinTransaction with PendingTransaction { String? idOverride; String? hexOverride; List? outputAddresses; - final Map? publicKeys; - Future Function()? commitOverride; @override String get id => idOverride ?? _tx.txId(); @@ -134,10 +129,6 @@ class PendingBitcoinTransaction with PendingTransaction { @override Future commit() async { - if (commitOverride != null) { - return commitOverride?.call(); - } - if (isMweb) { await _ltcCommit(); } else { diff --git a/cw_bitcoin/lib/psbt/signer.dart b/cw_bitcoin/lib/psbt/signer.dart deleted file mode 100644 index 1d0ceba8b..000000000 --- a/cw_bitcoin/lib/psbt/signer.dart +++ /dev/null @@ -1,263 +0,0 @@ -import 'dart:typed_data'; - -import 'package:bitcoin_base/bitcoin_base.dart'; -import 'package:blockchain_utils/blockchain_utils.dart'; -import 'package:collection/collection.dart'; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/bitcoin_unspent.dart'; -import 'package:cw_bitcoin/bitcoin_wallet.dart'; -import 'package:cw_bitcoin/utils.dart'; -import 'package:ledger_bitcoin/psbt.dart'; -import 'package:ledger_bitcoin/src/utils/buffer_writer.dart'; - -extension PsbtSigner on PsbtV2 { - Uint8List extractUnsignedTX({bool getSegwit = true}) { - final tx = BufferWriter()..writeUInt32(getGlobalTxVersion()); - - final isSegwit = getInputWitnessUtxo(0) != null; - if (isSegwit && getSegwit) { - tx.writeSlice(Uint8List.fromList([0, 1])); - } - - final inputCount = getGlobalInputCount(); - tx.writeVarInt(inputCount); - - for (var i = 0; i < inputCount; i++) { - tx - ..writeSlice(getInputPreviousTxid(i)) - ..writeUInt32(getInputOutputIndex(i)) - ..writeVarSlice(Uint8List(0)) - ..writeUInt32(getInputSequence(i)); - } - - final outputCount = getGlobalOutputCount(); - tx.writeVarInt(outputCount); - for (var i = 0; i < outputCount; i++) { - tx.writeUInt64(getOutputAmount(i)); - tx.writeVarSlice(getOutputScript(i)); - } - tx.writeUInt32(getGlobalFallbackLocktime() ?? 0); - return tx.buffer(); - } - - Future signWithUTXO( - List utxos, UTXOSignerCallBack signer, - [UTXOGetterCallBack? getTaprootPair]) async { - final raw = BytesUtils.toHexString(extractUnsignedTX(getSegwit: false)); - final tx = BtcTransaction.fromRaw(raw); - - /// when the transaction is taproot and we must use getTaproot transaction - /// digest we need all of inputs amounts and owner script pub keys - List taprootAmounts = []; - List