diff --git a/.github/workflows/automated_integration_test.yml b/.github/workflows/automated_integration_test.yml index 47b08c44d..84c680dda 100644 --- a/.github/workflows/automated_integration_test.yml +++ b/.github/workflows/automated_integration_test.yml @@ -55,7 +55,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: "3.27.0" + flutter-version: "3.27.4" channel: stable - name: Install package dependencies @@ -153,8 +153,8 @@ jobs: 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 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 @@ -168,7 +168,6 @@ 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 @@ -179,8 +178,7 @@ jobs: 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 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 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 index 507793bd8..9c3d82bc2 100644 --- a/.github/workflows/no_print_in_dart.yaml +++ b/.github/workflows/no_print_in_dart.yaml @@ -15,5 +15,5 @@ jobs: [[ "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" + echo "Please use printV from package: cw_core/utils/print_verbose.dart" exit 1 diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index f7c226ce4..8f6139747 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -9,7 +9,7 @@ jobs: PR_test_build: runs-on: linux-amd64 container: - image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly + image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 env: STORE_PASS: test@cake_wallet KEY_PASS: test@cake_wallet @@ -98,8 +98,8 @@ jobs: 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 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,7 +113,6 @@ 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 @@ -125,8 +124,7 @@ jobs: 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 @@ -255,11 +253,6 @@ jobs: - 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 diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml index f057b19e5..476a033a0 100644 --- a/.github/workflows/pr_test_build_linux.yml +++ b/.github/workflows/pr_test_build_linux.yml @@ -9,7 +9,7 @@ jobs: PR_test_build: runs-on: linux-amd64 container: - image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly + image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 env: STORE_PASS: test@cake_wallet KEY_PASS: test@cake_wallet @@ -91,8 +91,8 @@ jobs: 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 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 @@ -106,7 +106,6 @@ 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 @@ -118,8 +117,7 @@ jobs: 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 diff --git a/Dockerfile b/Dockerfile index 151b7af20..84179d645 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# 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 +# docker buildx build --push --pull --platform linux/amd64,linux/arm64 . -f Dockerfile -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 # Heavily inspired by cirrusci images # https://github.com/cirruslabs/docker-images-android/blob/master/sdk/tools/Dockerfile @@ -15,11 +15,11 @@ LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet ENV GOLANG_VERSION=1.24.1 # Pin Flutter version to latest known-working version -ENV FLUTTER_VERSION=3.27.0 +ENV FLUTTER_VERSION=3.27.4 # 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 +ENV ANDROID_SDK_TOOLS_VERSION=11076708 # Comes from https://developer.android.com/studio/releases/build-tools ENV ANDROID_PLATFORM_VERSION=35 ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0 @@ -164,12 +164,9 @@ RUN (addgroup kvm || true) && \ 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 \ + rustup target add --toolchain stable $target; \ done # Download and install Flutter @@ -178,11 +175,8 @@ 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 \ +RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} \ + && yes | flutter doctor --android-licenses \ && flutter doctor \ && chown -R root:root ${FLUTTER_HOME} diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 8283a7c8c..280a45b3c 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -111,8 +111,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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/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/birthday_cake.svg b/assets/images/birthday_cake.svg new file mode 100644 index 000000000..b5e31dddb --- /dev/null +++ b/assets/images/birthday_cake.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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_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/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/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/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/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_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/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/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_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/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/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index faf57258a..852e6ad0d 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,4 @@ -Add built-in Tor support (experimental) -Ledger improvements +Background sync improvements +Payment notifications UI/UX improvements Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index c49b895e3..c766c39ff 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,9 +1,5 @@ -Add built-in Tor support (experimental) -Add dEuro investments -Solana fixes/enhancements -Polygon fixes/enhancements -WalletConnect improvements -Ledger improvements -Payjoin improvements +Background sync improvements +Payment notifications +WalletConnect enhancements UI/UX improvements Bug fixes \ No newline at end of file diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index 0d985b237..e726217f5 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -20,7 +20,6 @@ BitcoinBaseAddress addressFromScript(Script script, 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: diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 9231022f6..a23b72660 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -266,12 +266,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { derivationPath: walletInfo.derivationInfo!.derivationPath!); } - @override - Future close({bool shouldCleanup = false}) async { - payjoinManager.cleanupSessions(); - super.close(shouldCleanup: shouldCleanup); - } - late final PayjoinManager payjoinManager; bool get isPayjoinAvailable => unspentCoinsInfo.values diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index d84d958be..0fefe4e57 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -31,10 +31,12 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S final PayjoinManager payjoinManager; + @observable payjoin.Receiver? currentPayjoinReceiver; - @observable - String? payjoinEndpoint = null; + @computed + String? get payjoinEndpoint => + currentPayjoinReceiver?.pjUriBuilder().build().pjEndpoint(); @override String getAddress( @@ -57,32 +59,16 @@ 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; - } + currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress); + + payjoinManager.resumeSessions(); } - @action Future newPayjoinReceiver() async { - try { - currentPayjoinReceiver = await payjoinManager.getUnusedReceiver(primaryAddress); - payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint(); + currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress); - payjoinManager.spawnReceiver(receiver: currentPayjoinReceiver!); - } catch (e) { - printV(e); - // Ignore Connectivity errors - if (!e.toString().contains("error sending request for url")) rethrow; - } + printV("Initializing new Payjoin Receiver"); + payjoinManager.spawnNewReceiver(receiver: currentPayjoinReceiver!); } } diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 2ddd30df6..1f5c369e3 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -5,8 +5,6 @@ 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 +42,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 +72,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 +105,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 { diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index bb9cea1bc..35c15682c 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -4,7 +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'; @@ -50,6 +49,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'; @@ -493,9 +493,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; @@ -1175,18 +1176,20 @@ 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, + publicKeys: estimatedTx.publicKeys + )..addListener((transaction) async { transactionHistory.addOne(transaction); if (estimatedTx.spendsSilentPayment) { transactionHistory.transactions.values.forEach((tx) { @@ -1877,17 +1880,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) { diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 08c56c600..662d70d67 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -464,9 +464,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(); diff --git a/cw_bitcoin/lib/payjoin/manager.dart b/cw_bitcoin/lib/payjoin/manager.dart index 95a523d89..b80fa777c 100644 --- a/cw_bitcoin/lib/payjoin/manager.dart +++ b/cw_bitcoin/lib/payjoin/manager.dart @@ -6,7 +6,6 @@ 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'; @@ -17,7 +16,6 @@ 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 { @@ -30,16 +28,13 @@ class PayjoinManager { 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 Future randomOhttpRelayUrl() => PayjoinUri.Url.fromStr( + 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); @@ -47,13 +42,13 @@ class PayjoinManager { if (session.isSenderSession) { printV("Resuming Payjoin Sender Session ${session.pjUri!}"); return _spawnSender( - sender: Sender.fromJson(json: session.sender!), + sender: Sender.fromJson(session.sender!), pjUri: session.pjUri!, ); } - final receiver = Receiver.fromJson(json: session.receiver!); + final receiver = Receiver.fromJson(session.receiver!); printV("Resuming Payjoin Receiver Session ${receiver.id()}"); - return spawnReceiver(receiver: receiver); + return _spawnReceiver(receiver: receiver); }); printV("Resumed ${spawnedSessions.length} Payjoin Sessions"); @@ -70,12 +65,7 @@ class PayjoinManager { 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); + return senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu); } catch (e) { throw Exception('Error initializing Payjoin Sender: $e'); } @@ -121,13 +111,15 @@ class PayjoinManager { } } catch (e) { _cleanupSession(pjUri); - await _payjoinStorage.markSenderSessionUnrecoverable(pjUri, e.toString()); - completer.complete(); + printV(e); + await _payjoinStorage.markSenderSessionUnrecoverable(pjUri); + completer.completeError(e); } } else if (message is PayjoinSessionError) { _cleanupSession(pjUri); if (message is UnrecoverableError) { - await _payjoinStorage.markSenderSessionUnrecoverable(pjUri, message.message); + printV(message.message); + await _payjoinStorage.markSenderSessionUnrecoverable(pjUri); completer.complete(); } else if (message is RecoverableError) { completer.complete(); @@ -147,41 +139,42 @@ class PayjoinManager { return completer.future; } - Future getUnusedReceiver(String address, + Future initReceiver(String address, [bool isTestnet = false]) async { - final session = _payjoinStorage.getUnusedActiveReceiverSession(_wallet.id); + try { + final payjoinDirectory = + await PayjoinUri.Url.fromStr(payjoinDirectoryUrl); - if (session != null) { - await PayjoinUri.Url.fromStr(payjoinDirectoryUrl); + final ohttpKeys = await PayjoinUri.fetchOhttpKeys( + ohttpRelay: await randomOhttpRelayUrl(), + payjoinDirectory: payjoinDirectory, + ); - return Receiver.fromJson(json: session.receiver!); + final receiver = await Receiver.create( + address: address, + network: isTestnet ? Network.testnet : Network.bitcoin, + directory: payjoinDirectory, + ohttpKeys: ohttpKeys, + ohttpRelay: await randomOhttpRelayUrl(), + ); + + await _payjoinStorage.insertReceiverSession(receiver, _wallet.id); + + return receiver; + } catch (e) { + throw Exception('Error initializing Payjoin Receiver: $e'); } - - 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); - + Future spawnNewReceiver({ + required Receiver receiver, + bool isTestnet = false, + }) async { await _payjoinStorage.insertReceiverSession(receiver, _wallet.id); - - return receiver; + return _spawnReceiver(isTestnet: isTestnet, receiver: receiver); } - Future spawnReceiver({ + Future _spawnReceiver({ required Receiver receiver, bool isTestnet = false, }) async { @@ -201,8 +194,7 @@ class PayjoinManager { rawAmount = getOutputAmountFromTx(tx, _wallet); break; case PayjoinReceiverRequestTypes.checkIsOwned: - (_wallet.walletAddresses as BitcoinWalletAddresses) - .newPayjoinReceiver(); + (_wallet.walletAddresses as BitcoinWalletAddresses).newPayjoinReceiver(); _payjoinStorage.markReceiverSessionInProgress(receiver.id()); final inputScript = message['input_script'] as Uint8List; @@ -226,10 +218,6 @@ class PayjoinManager { case PayjoinReceiverRequestTypes.getCandidateInputs: utxos = _wallet.getUtxoWithPrivateKeys(); - if (utxos.isEmpty) { - await _wallet.updateAllUnspents(); - utxos = _wallet.getUtxoWithPrivateKeys(); - } mainToIsolateSendPort?.send({ 'requestId': message['requestId'], 'result': utxos, 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 index c56148de2..a499660b0 100644 --- a/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart +++ b/cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart @@ -4,16 +4,14 @@ 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:http/http.dart' as http; 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, @@ -29,7 +27,7 @@ class PayjoinReceiverWorker { final pendingRequests = >{}; PayjoinReceiverWorker._(this.sendPort); - static final client = ProxyWrapper().getHttpIOClient(); + static Future run(List args) async { await pj.core.init(); @@ -43,10 +41,11 @@ class PayjoinReceiverWorker { receivePort.listen(worker.handleMessage); try { - final receiver = Receiver.fromJson(json: receiverJson); + final httpClient = http.Client(); + final receiver = Receiver.fromJson(receiverJson); final uncheckedProposal = - await worker.receiveUncheckedProposal(receiver); + await worker.receiveUncheckedProposal(httpClient, receiver); final originalTx = await uncheckedProposal.extractTxToScheduleBroadcast(); sendPort.send({ @@ -57,14 +56,14 @@ class PayjoinReceiverWorker { final payjoinProposal = await worker.processPayjoinProposal( uncheckedProposal, ); - final psbt = await worker.sendFinalProposal(payjoinProposal); + final psbt = await worker.sendFinalProposal(httpClient, payjoinProposal); sendPort.send({ 'type': PayjoinReceiverRequestTypes.proposalSent, 'psbt': psbt, }); } catch (e) { if (e is HttpException || - (e is very_insecure_http_do_not_use.ClientException && + (e is http.ClientException && e.message.contains("Software caused connection abort"))) { sendPort.send(PayjoinSessionError.recoverable(e.toString())); } else { @@ -98,16 +97,15 @@ class PayjoinReceiverWorker { return completer.future; } - Future receiveUncheckedProposal(Receiver session) async { + Future receiveUncheckedProposal( + http.Client httpClient, Receiver session) async { while (true) { printV("Polling for Proposal (${session.id()})"); - final extractReq = await session.extractReq( - ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(), - ); + final extractReq = await session.extractReq(); final request = extractReq.$1; final url = Uri.parse(request.url.asString()); - final httpRequest = await client.post(url, + final httpRequest = await httpClient.post(url, headers: {'Content-Type': request.contentType}, body: request.body); final proposal = await session.processRes( @@ -116,14 +114,13 @@ class PayjoinReceiverWorker { } } - Future sendFinalProposal(PayjoinProposal finalProposal) async { - final req = await finalProposal.extractReq( - ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(), - ); + Future sendFinalProposal( + http.Client httpClient, PayjoinProposal finalProposal) async { + final req = await finalProposal.extractV2Req(); final proposalReq = req.$1; final proposalCtx = req.$2; - final request = await client.post( + final request = await httpClient.post( Uri.parse(proposalReq.url.asString()), headers: {"Content-Type": proposalReq.contentType}, body: proposalReq.body, @@ -174,7 +171,7 @@ class PayjoinReceiverWorker { final listUnspent = await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs); final unspent = listUnspent as List; - if (unspent.isEmpty) throw RecoverableError('No unspent outputs available'); + if (unspent.isEmpty) throw Exception('No unspent outputs available'); final selectedUtxo = await _inputPairFromUtxo(unspent[0]); final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]); @@ -217,6 +214,6 @@ class PayjoinReceiverWorker { sequence: 0, ); - return InputPair.newInstance(txin: txin, psbtin: psbtin); + return InputPair.newInstance(txin, psbtin); } } diff --git a/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart b/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart index 7e85cc773..f720bac01 100644 --- a/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart +++ b/cw_bitcoin/lib/payjoin/payjoin_send_worker.dart @@ -5,12 +5,10 @@ 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:http/http.dart' as http; 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, @@ -31,7 +29,7 @@ class PayjoinSenderWorker { final senderJson = args[1] as String; final pjUrl = args[2] as String; - final sender = Sender.fromJson(json: senderJson); + final sender = Sender.fromJson(senderJson); final worker = PayjoinSenderWorker._(sendPort, pjUrl); try { @@ -44,17 +42,19 @@ class PayjoinSenderWorker { sendPort.send(e); } } - final client = ProxyWrapper().getHttpIOClient(); /// Run a payjoin sender (V2 protocol first, fallback to V1). Future runSender(Sender sender) async { + final httpClient = http.Client(); try { - return await _runSenderV2(sender); + return await _runSenderV2(sender, httpClient); } catch (e) { printV(e); - if (e is pj_error.FfiCreateRequestError) { - return await _runSenderV1(sender); + if (e is PayjoinException && + // TODO condition on error type instead of message content + e.message?.contains('parse receiver public key') == true) { + return await _runSenderV1(sender, httpClient); } else if (e is HttpException) { printV(e); throw Exception(PayjoinSessionError.recoverable(e.toString())); @@ -65,14 +65,13 @@ class PayjoinSenderWorker { } /// Attempt to send payjoin using the V2 of the protocol. - Future _runSenderV2(Sender sender) async { + Future _runSenderV2(Sender sender, http.Client httpClient) async { try { final postRequest = await sender.extractV2( - ohttpProxyUrl: - await pj_uri.Url.fromStr(PayjoinManager.randomOhttpRelayUrl()), + ohttpProxyUrl: await PayjoinManager.randomOhttpRelayUrl(), ); - final postResult = await _postRequest(postRequest.$1); + final postResult = await _postRequest(httpClient, postRequest.$1); final getContext = await postRequest.$2.processResponse(response: postResult); @@ -84,7 +83,7 @@ class PayjoinSenderWorker { final getRequest = await getContext.extractReq( ohttpRelay: await PayjoinManager.randomOhttpRelayUrl(), ); - final getRes = await _postRequest(getRequest.$1); + final getRes = await _postRequest(httpClient, getRequest.$1); final proposalPsbt = await getContext.processResponse( response: getRes, ohttpCtx: getRequest.$2, @@ -98,20 +97,20 @@ class PayjoinSenderWorker { } /// Attempt to send payjoin using the V1 of the protocol. - Future _runSenderV1(Sender sender) async { + Future _runSenderV1(Sender sender, http.Client httpClient) async { try { final postRequest = await sender.extractV1(); - final response = await _postRequest(postRequest.$1); + final response = await _postRequest(httpClient, 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'); + } catch (e) { + throw PayjoinSessionError.unrecoverable('Send V1 payjoin error: $e'); } } - Future> _postRequest(Request req) async { + Future> _postRequest(http.Client client, Request req) async { final httpRequest = await client.post(Uri.parse(req.url.asString()), headers: {'Content-Type': req.contentType}, body: req.body); diff --git a/cw_bitcoin/lib/payjoin/storage.dart b/cw_bitcoin/lib/payjoin/storage.dart index 5fb9d5716..9c1c83253 100644 --- a/cw_bitcoin/lib/payjoin/storage.dart +++ b/cw_bitcoin/lib/payjoin/storage.dart @@ -23,14 +23,6 @@ class PayjoinStorage { ), ); - 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}")!; @@ -84,11 +76,10 @@ class PayjoinStorage { await session.save(); } - Future markSenderSessionUnrecoverable(String pjUrl, String reason) async { + Future markSenderSessionUnrecoverable(String pjUrl) async { final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!; session.status = PayjoinSessionStatus.unrecoverable.name; - session.error = reason; await session.save(); } diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index c2987894c..e21da4f1d 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -5,39 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" url: "https://pub.dev" source: hosted - version: "76.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.3" + version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" url: "https://pub.dev" source: hosted - version: "6.11.0" + version: "4.7.0" args: dependency: transitive description: name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.6.0" asn1lib: dependency: transitive description: name: asn1lib - sha256: "1c296cd268f486cabcc3930e9b93a8133169305f18d722916e675959a88f6d2c" + sha256: "4bae5ae63e6d6dd17c4aac8086f3dec26c0236f6a0f03416c6c19d830c367cf5" url: "https://pub.dev" source: hosted - version: "1.5.9" + version: "1.5.8" async: dependency: transitive description: @@ -85,7 +80,7 @@ packages: description: path: "." ref: cake-update-v9 - resolved-ref: bb4318511312a454fd91bf49042e25ecc855e4ac + resolved-ref: "86969a14e337383e14965f5fb45a72a63e5009bc" url: "https://github.com/cake-tech/bitcoin_base" source: git version: "4.7.0" @@ -126,10 +121,10 @@ packages: dependency: transitive description: name: build - sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.1" build_cli_annotations: dependency: transitive description: @@ -142,42 +137,42 @@ packages: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.2" build_resolvers: dependency: "direct dev" description: name: build_resolvers - sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.2.10" built_collection: dependency: transitive description: @@ -190,10 +185,10 @@ packages: dependency: transitive description: name: built_value - sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27" + sha256: "8b158ab94ec6913e480dc3f752418348b5ae099eb75868b5f4775f0572999c61" url: "https://pub.dev" source: hosted - version: "8.10.1" + version: "8.9.4" cake_backup: dependency: transitive description: @@ -301,10 +296,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" url: "https://pub.dev" source: hosted - version: "2.3.8" + version: "2.2.4" dart_varuint_bitcoin: dependency: transitive description: @@ -394,10 +389,10 @@ packages: dependency: transitive description: name: flutter_rust_bridge - sha256: "5a5c7a5deeef2cc2ffe6076a33b0429f4a20ceac22a397297aed2b1eb067e611" + sha256: "3292ad6085552987b8b3b9a7e5805567f4013372d302736b702801acb001ee00" url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.7.1" flutter_test: dependency: "direct dev" description: flutter @@ -407,10 +402,10 @@ packages: dependency: transitive description: name: flutter_web_bluetooth - sha256: ad26a1b3fef95b86ea5f63793b9a0cdc1a33490f35d754e4e711046cae3ebbf8 + sha256: "1363831def5eed1e1064d1eca04e8ccb35446e8f758579c3c519e156b77926da" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.0" flutter_web_plugins: dependency: transitive description: flutter @@ -420,10 +415,10 @@ packages: dependency: transitive description: name: freezed_annotation - sha256: c87ff004c8aa6af2d531668b46a4ea379f7191dc6dfa066acd53d506da6e044b + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "2.4.4" frontend_server_client: dependency: transitive description: @@ -444,18 +439,18 @@ packages: dependency: transitive description: name: google_identity_services_web - sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" + sha256: "55580f436822d64c8ff9a77e37d61f5fb1e6c7ec9d632a43ee324e2a05c3c6c9" url: "https://pub.dev" source: hosted - version: "0.3.3+1" + version: "0.3.3" googleapis_auth: dependency: transitive description: name: googleapis_auth - sha256: b81fe352cc4a330b3710d2b7ad258d9bcef6f909bb759b306bf42973a7d046db + sha256: befd71383a955535060acde8792e7efc11d2fccd03dd1d3ec434e85b68775938 url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "1.6.0" graphs: dependency: transitive description: @@ -468,10 +463,10 @@ packages: dependency: "direct main" description: name: grpc - sha256: "30e1edae6846b163a64f6d8716e3443980fe1f7d2d1f086f011d24ea186f2582" + sha256: "5b99b7a420937d4361ece68b798c9af8e04b5bc128a7859f2a4be87427694813" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.1" hex: dependency: transitive description: @@ -492,18 +487,18 @@ packages: dependency: "direct dev" description: name: hive_generator - sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "1.1.3" http: dependency: "direct main" description: name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" http2: dependency: transitive description: @@ -524,10 +519,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.1.2" + version: "4.0.2" intl: dependency: "direct main" description: @@ -597,10 +592,10 @@ packages: dependency: "direct main" description: name: ledger_flutter_plus - sha256: "531da5daba5731d9eca2732881ef2f039b97bf8aa3564e7098dfa99a9b07a8e6" + sha256: "1c03f3c4a9754b5f0170a9eb9552ec54fa86e985f8ee71a255ee2c5629b53d31" url: "https://pub.dev" source: hosted - version: "1.5.3" + version: "1.5.1" ledger_litecoin: dependency: "direct main" description: @@ -626,14 +621,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" - url: "https://pub.dev" - source: hosted - version: "0.1.3-main.0" matcher: dependency: transitive description: @@ -678,10 +665,10 @@ packages: dependency: "direct dev" description: name: mobx_codegen - sha256: e0abbbc651a69550440f6b65c99ec222a1e2a4afd7baec8ba0f3088c7ca582a8 + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.7.1" + version: "2.3.0" nested: dependency: transitive description: @@ -703,10 +690,10 @@ packages: dependency: transitive description: name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.1" path: dependency: transitive description: @@ -727,10 +714,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.2.15" path_provider_foundation: dependency: transitive description: @@ -767,11 +754,11 @@ packages: dependency: "direct main" description: path: "." - ref: da83a23f3a011cb49eb3b6513cd485b3fb8867ff - resolved-ref: da83a23f3a011cb49eb3b6513cd485b3fb8867ff - url: "https://github.com/OmarHatem28/payjoin-flutter" + ref: "6a3eb32fb9467ac12e7b75d3de47de4ca44fd88c" + resolved-ref: "6a3eb32fb9467ac12e7b75d3de47de4ca44fd88c" + url: "https://github.com/konstantinullrich/payjoin-flutter" source: git - version: "0.23.0" + version: "0.21.0" petitparser: dependency: transitive description: @@ -824,26 +811,26 @@ packages: dependency: transitive description: name: provider - sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.1.2" pub_semver: dependency: transitive description: name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.5" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.4.0" quiver: dependency: transitive description: @@ -872,18 +859,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + sha256: a768fc8ede5f0c8e6150476e14f38e2417c0864ca36bb4582be8e21925a03c22 url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.4.6" shared_preferences_foundation: dependency: transitive description: @@ -928,18 +915,18 @@ packages: dependency: transitive description: name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "2.0.1" sky_engine: dependency: transitive description: flutter @@ -948,37 +935,27 @@ packages: socks5_proxy: dependency: transitive description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: "direct main" - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" url: "https://pub.dev" source: hosted - version: "1.3.5" + version: "1.3.3" source_span: dependency: transitive description: @@ -996,6 +973,14 @@ packages: url: "https://github.com/cake-tech/sp_scanner" source: git version: "0.0.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: @@ -1048,19 +1033,10 @@ packages: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" - tor_binary: - dependency: transitive - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" + version: "1.0.2" tuple: dependency: transitive description: @@ -1081,10 +1057,10 @@ packages: dependency: transitive description: name: universal_ble - sha256: "35d210e93a5938c6a6d1fd3c710cf4ac90b1bdd1b11c8eb2beeb32600672e6e6" + sha256: "1fad089150a29db82b3b7d60327e18c5ad6b3a5bb509defc1c690b0a76b9c098" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.15.0" universal_platform: dependency: transitive description: @@ -1101,6 +1077,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_math: dependency: transitive description: @@ -1137,18 +1121,18 @@ packages: dependency: transitive description: name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" xdg_directories: dependency: transitive description: @@ -1182,5 +1166,5 @@ packages: source: hosted version: "2.2.2" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.27.4" diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index c24732c3a..f45258f92 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -42,8 +42,8 @@ dependencies: url: https://github.com/cake-tech/bech32.git payjoin_flutter: git: - url: https://github.com/OmarHatem28/payjoin-flutter - ref: da83a23f3a011cb49eb3b6513cd485b3fb8867ff #cake-v2 + url: https://github.com/konstantinullrich/payjoin-flutter + ref: 6a3eb32fb9467ac12e7b75d3de47de4ca44fd88c #cake-v1 ledger_flutter_plus: ^1.4.1 ledger_bitcoin: git: @@ -54,18 +54,14 @@ dependencies: git: url: https://github.com/cake-tech/ledger-flutter-plus-plugins path: packages/ledger-litecoin - socks_socket: - git: - url: https://github.com/sneurlax/socks_socket - ref: e6232c53c1595469931ababa878759a067c02e94 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 - build_resolvers: ^2.4.4 + build_runner: ^2.4.7 + build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 dependency_overrides: watcher: ^1.1.0 diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index e78261f9a..9a5c4f14f 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://cakewallet.com environment: sdk: '>=2.19.0 <3.0.0' - flutter: ">=1.20.0" + flutter: ">=1.17.0" dependencies: flutter: @@ -33,9 +33,9 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 dependency_overrides: watcher: ^1.1.0 diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 0d6ab9f3a..cb8485ec5 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -111,8 +111,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.zano, CryptoCurrency.ton, CryptoCurrency.flip, - CryptoCurrency.deuro, - CryptoCurrency.usdtbsc, + CryptoCurrency.deuro ]; static const havenCurrencies = [ @@ -233,8 +232,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const ton = CryptoCurrency(title: 'TON', fullName: 'Toncoin', raw: 95, name: 'ton', iconPath: 'assets/images/ton_icon.png', decimals: 8); static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/images/zano_icon.png', decimals: 12); static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18); - static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png', decimals: 18); - static const usdtbsc = CryptoCurrency(title: 'USDT', tag: 'BSC', fullName: 'USDT Binance coin', raw: 99, name: 'usdtbsc', iconPath: 'assets/images/usdtbsc_icon.png', decimals: 18); + static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Digital Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png', decimals: 18); static final Map _rawCurrencyMap = [...all, ...havenCurrencies].fold>({}, (acc, item) { diff --git a/cw_core/lib/get_height_by_date.dart b/cw_core/lib/get_height_by_date.dart index 4786336af..aee12b423 100644 --- a/cw_core/lib/get_height_by_date.dart +++ b/cw_core/lib/get_height_by_date.dart @@ -1,7 +1,7 @@ -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:intl/intl.dart'; import 'dart:convert'; +import 'package:http/http.dart' as http; // FIXME: Hardcoded values; Works only for monero @@ -234,14 +234,10 @@ int getHavenHeightByDate({required DateTime date}) { } Future getHavenCurrentHeight() async { - final req = await ProxyWrapper().getHttpClient() - .getUrl(Uri.parse('https://explorer.havenprotocol.org/api/networkinfo')) - .timeout(Duration(seconds: 15)); - final response = await req.close(); - final stringResponse = await response.transform(utf8.decoder).join(); + final response = await http.get(Uri.parse('https://explorer.havenprotocol.org/api/networkinfo')); if (response.statusCode == 200) { - final info = jsonDecode(stringResponse); + final info = jsonDecode(response.body); return info['data']['height'] as int; } else { throw Exception('Failed to load current blockchain height'); @@ -273,13 +269,13 @@ const bitcoinDates = { }; Future getBitcoinHeightByDateAPI({required DateTime date}) async { - final req = await ProxyWrapper().getHttpClient() - .getUrl(Uri.parse("https://mempool.cakewallet.com/api/v1/mining/blocks/timestamp/${(date.millisecondsSinceEpoch / 1000).round()}")) - .timeout(Duration(seconds: 15)); - final response = await req.close(); - final stringResponse = await response.transform(utf8.decoder).join(); + final response = await http.get( + Uri.parse( + "https://mempool.cakewallet.com/api/v1/mining/blocks/timestamp/${(date.millisecondsSinceEpoch / 1000).round()}", + ), + ); - return jsonDecode(stringResponse)['height'] as int; + return jsonDecode(response.body)['height'] as int; } int getBitcoinHeightByDate({required DateTime date}) { diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index fdffb844b..38fcde9e1 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -1,12 +1,12 @@ import 'dart:io'; import 'package:cw_core/keyable.dart'; -import 'package:cw_core/utils/proxy_socket/abstract.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'dart:convert'; +import 'package:http/http.dart' as http; import 'package:hive/hive.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:http/io_client.dart' as ioc; import 'dart:math' as math; import 'package:convert/convert.dart'; @@ -184,17 +184,23 @@ class Node extends HiveObject with Keyable { final body = {'jsonrpc': '2.0', 'id': '0', 'method': "getinfo"}; try { + final authenticatingClient = HttpClient(); + authenticatingClient.badCertificateCallback = + ((X509Certificate cert, String host, int port) => true); + + final http.Client client = ioc.IOClient(authenticatingClient); + final jsonBody = json.encode(body); - final response = await ProxyWrapper().post( - clearnetUri: rpcUri, + final response = await client.post( + rpcUri, headers: {'Content-Type': 'application/json'}, body: jsonBody, ); - - final resBody = json.decode(response.body) as Map; + printV("node check response: ${response.body}"); + final resBody = json.decode(response.body) as Map; return resBody['result']['height'] != null; } catch (e) { printV("error: $e"); @@ -212,7 +218,11 @@ class Node extends HiveObject with Keyable { final body = {'jsonrpc': '2.0', 'id': '0', 'method': methodName}; try { - final client = ProxyWrapper().getHttpIOClient(); + final authenticatingClient = HttpClient(); + authenticatingClient.badCertificateCallback = + ((X509Certificate cert, String host, int port) => true); + + final http.Client client = ioc.IOClient(authenticatingClient); final jsonBody = json.encode(body); @@ -232,15 +242,15 @@ class Node extends HiveObject with Keyable { return !(response['offline'] as bool); } - final responseString = await response.body; + printV("node check response: ${response.body}"); - if ((responseString.contains("400 Bad Request") // Some other generic error + if ((response.body.contains("400 Bad Request") // Some other generic error || - responseString.contains("plain HTTP request was sent to HTTPS port") // Cloudflare + response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare || response.headers["location"] != null // Generic reverse proxy || - responseString + response.body .contains("301 Moved Permanently") // Poorly configured generic reverse proxy ) && !(useSSL ?? false)) { @@ -267,16 +277,15 @@ class Node extends HiveObject with Keyable { } Future requestNodeWithProxy() async { - if (!isValidProxyAddress && !CakeTor.instance.enabled) { + if (!isValidProxyAddress /* && !Tor.instance.enabled*/) { return false; } String? proxy = socksProxyAddress; - if ((proxy?.isEmpty ?? true) && CakeTor.instance.enabled) { - proxy = "${InternetAddress.loopbackIPv4.address}:${CakeTor.instance.port}"; - } - printV("proxy: $proxy"); + // if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) { + // proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + // } if (proxy == null) { return false; } @@ -296,9 +305,13 @@ class Node extends HiveObject with Keyable { // you try to communicate with it Future requestElectrumServer() async { try { - final ProxySocket socket; - socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, uri.host, uri.port); - + final Socket socket; + if (useSSL == true) { + socket = await SecureSocket.connect(uri.host, uri.port, + timeout: Duration(seconds: 5), onBadCertificate: (_) => true); + } else { + socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5)); + } socket.destroy(); return true; @@ -309,8 +322,8 @@ class Node extends HiveObject with Keyable { Future requestNanoNode() async { try { - final response = await ProxyWrapper().post( - clearnetUri: uri, + final response = await http.post( + uri, headers: {"Content-Type": "application/json", "nano-app": "cake-wallet"}, body: jsonEncode( { @@ -319,8 +332,7 @@ class Node extends HiveObject with Keyable { }, ), ); - - final data = jsonDecode(response.body); + final data = await jsonDecode(response.body); if (response.statusCode != 200 || data["error"] != null || data["balance"] == null || @@ -336,14 +348,13 @@ class Node extends HiveObject with Keyable { Future requestEthereumServer() async { try { - final req = await ProxyWrapper().getHttpClient() - .getUrl(uri,) - .timeout(Duration(seconds: 15)); - final response = await req.close(); + final response = await http.get( + uri, + headers: {'Content-Type': 'application/json'}, + ); return response.statusCode >= 200 && response.statusCode < 300; - } catch (err) { - printV("Failed to request ethereum server: $err"); + } catch (_) { return false; } } @@ -451,7 +462,7 @@ class DaemonRpc { /// Perform a JSON-RPC call with Digest Authentication. Future> call(String method, Map params) async { - final client = ProxyWrapper().getHttpIOClient(); + final http.Client client = http.Client(); final DigestAuth digestAuth = DigestAuth(username, password); // Initial request to get the `WWW-Authenticate` header. diff --git a/cw_core/lib/solana_rpc_http_service.dart b/cw_core/lib/solana_rpc_http_service.dart index 1c6e975aa..fbe9a29dc 100644 --- a/cw_core/lib/solana_rpc_http_service.dart +++ b/cw_core/lib/solana_rpc_http_service.dart @@ -1,19 +1,20 @@ import 'dart:convert'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart'; import 'package:on_chain/solana/solana.dart'; class SolanaRPCHTTPService implements SolanaJSONRPCService { SolanaRPCHTTPService( - {required this.url, - this.defaultRequestTimeout = const Duration(seconds: 30)}); + {required this.url, Client? client, this.defaultRequestTimeout = const Duration(seconds: 30)}) + : client = client ?? Client(); @override final String url; + final Client client; final Duration defaultRequestTimeout; - Future> call(SolanaRequestDetails params, - [Duration? timeout]) async { - final response = await ProxyWrapper().post( - clearnetUri: Uri.parse(url), + @override + Future> call(SolanaRequestDetails params, [Duration? timeout]) async { + final response = await client.post( + Uri.parse(url), body: params.toRequestBody(), headers: { 'Content-Type': 'application/json', diff --git a/cw_core/lib/utils/proxy_logger/abstract.dart b/cw_core/lib/utils/proxy_logger/abstract.dart deleted file mode 100644 index 303b640f1..000000000 --- a/cw_core/lib/utils/proxy_logger/abstract.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'dart:typed_data'; -import 'package:http/http.dart' as very_insecure_http_do_not_use; - -enum RequestNetwork { - clearnet, - tor, -} - -enum RequestMethod { - get, - post, - put, - delete, - - newHttpClient, - newHttpIOClient, - newProxySocket, -} - -abstract class ProxyLogger { - void log({ - required Uri? uri, - required RequestMethod method, - required Uint8List body, - required very_insecure_http_do_not_use.Response? response, - required RequestNetwork network, - required String? error, - }); -} \ No newline at end of file diff --git a/cw_core/lib/utils/proxy_logger/memory_proxy_logger.dart b/cw_core/lib/utils/proxy_logger/memory_proxy_logger.dart deleted file mode 100644 index e2929da12..000000000 --- a/cw_core/lib/utils/proxy_logger/memory_proxy_logger.dart +++ /dev/null @@ -1,63 +0,0 @@ -import 'dart:typed_data'; - -import 'package:cw_core/utils/proxy_logger/abstract.dart'; -import 'package:http/http.dart' as very_insecure_http_do_not_use; - -class MemoryProxyLoggerEntry { - MemoryProxyLoggerEntry({ - required this.trace, - required this.uri, - required this.body, - required this.network, - required this.method, - required this.response, - required this.error, - }) : time = DateTime.now(); - - final StackTrace trace; - final Uri? uri; - final Uint8List body; - final RequestNetwork network; - final very_insecure_http_do_not_use.Response? response; - final RequestMethod method; - final String? error; - final DateTime time; - @override - String toString() => """MemoryProxyLoggerEntry( - uri: $uri, - body: $body, - network: $network, - method: $method, - response: - code: ${response?.statusCode}, - headers: ${response?.headers}, - body: ${response?.body}, - error: $error, - time: $time, - trace: ${trace} -);"""; -} - -class MemoryProxyLogger implements ProxyLogger { - static List logs = []; - @override - void log({ - required Uri? uri, - required RequestMethod method, - required Uint8List body, - required very_insecure_http_do_not_use.Response? response, - required RequestNetwork network, - required String? error, - }) { - final trace = StackTrace.current; - logs.add(MemoryProxyLoggerEntry( - method: method, - trace: trace, - uri: uri, - body: body, - network: network, - response: response, - error: error,), - ); - } -} \ No newline at end of file diff --git a/cw_core/lib/utils/proxy_logger/silent_logger.dart b/cw_core/lib/utils/proxy_logger/silent_logger.dart deleted file mode 100644 index 1cea0d011..000000000 --- a/cw_core/lib/utils/proxy_logger/silent_logger.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'dart:typed_data'; - -import 'package:cw_core/utils/proxy_logger/abstract.dart'; -import 'package:http/http.dart' as very_insecure_http_do_not_use; - -// we are not doing anything -class SilentProxyLogger implements ProxyLogger { - @override - void log({ - required Uri? uri, - required RequestMethod method, - required Uint8List body, - required very_insecure_http_do_not_use.Response? response, - required RequestNetwork network, - required String? error, - }) {} -} \ No newline at end of file diff --git a/cw_core/lib/utils/proxy_socket/abstract.dart b/cw_core/lib/utils/proxy_socket/abstract.dart deleted file mode 100644 index b4b628f74..000000000 --- a/cw_core/lib/utils/proxy_socket/abstract.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:cw_core/utils/proxy_socket/insecure.dart'; -import 'package:cw_core/utils/proxy_socket/secure.dart'; -import 'package:cw_core/utils/proxy_socket/socks.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; -import 'package:socks_socket/socks_socket.dart'; - -class ProxyAddress { - final String host; - final int port; - - ProxyAddress({required this.host, required this.port}); -} - -abstract class ProxySocket { - static Future connect(bool sslEnabled, ProxyAddress address, {Duration? connectionTimeout}) async { - if (CakeTor.instance.started) { - var socksSocket = await SOCKSSocket.create( - proxyHost: InternetAddress.loopbackIPv4.address, - proxyPort: CakeTor.instance.port, - sslEnabled: sslEnabled, - ); - await socksSocket.connect(); - await socksSocket.connectTo(address.host, address.port); - return ProxySocketSocks(socksSocket); - } - if (sslEnabled == false) { - return ProxySocketInsecure(await Socket.connect(address.host, address.port, timeout: connectionTimeout)); - } else { - return ProxySocketSecure(await SecureSocket.connect( - address.host, - address.port, - timeout: connectionTimeout, - onBadCertificate: (_) => true, - )); - } - } - - Future close(); - Future destroy(); - Future write(String data); - StreamSubscription> listen(Function(Uint8List event) onData, {Function (Object error)? onError, Function ()? onDone, bool cancelOnError = true}); - ProxyAddress get address; -} \ No newline at end of file diff --git a/cw_core/lib/utils/proxy_socket/insecure.dart b/cw_core/lib/utils/proxy_socket/insecure.dart deleted file mode 100644 index aeac474d7..000000000 --- a/cw_core/lib/utils/proxy_socket/insecure.dart +++ /dev/null @@ -1,34 +0,0 @@ - -import 'package:cw_core/utils/proxy_socket/abstract.dart'; -import 'dart:async'; -import 'dart:typed_data'; -import 'dart:io'; - -class ProxySocketInsecure implements ProxySocket { - final Socket socket; - - ProxySocketInsecure(this.socket); - - ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort); - - @override - Future close() => socket.close(); - - @override - Future destroy() async => socket.destroy(); - - @override - Future write(String data) async => socket.write(data); - - @override - StreamSubscription> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) { - return socket.listen( - (data) { - onData(Uint8List.fromList(data)); - }, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError, - ); - } -} \ No newline at end of file diff --git a/cw_core/lib/utils/proxy_socket/secure.dart b/cw_core/lib/utils/proxy_socket/secure.dart deleted file mode 100644 index 2efd13ee4..000000000 --- a/cw_core/lib/utils/proxy_socket/secure.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:cw_core/utils/proxy_socket/abstract.dart'; - -class ProxySocketSecure implements ProxySocket { - final SecureSocket socket; - - ProxySocketSecure(this.socket); - - ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort); - - @override - Future close() => socket.close(); - - @override - Future destroy() async => socket.destroy(); - - @override - Future write(String data) async => socket.write(data); - - @override - StreamSubscription> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) { - return socket.listen( - (data) { - onData(Uint8List.fromList(data)); - }, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError, - ); - } -} diff --git a/cw_core/lib/utils/proxy_socket/socks.dart b/cw_core/lib/utils/proxy_socket/socks.dart deleted file mode 100644 index a4e5ddeb6..000000000 --- a/cw_core/lib/utils/proxy_socket/socks.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'dart:async'; -import 'dart:typed_data'; - -import 'package:cw_core/utils/proxy_socket/abstract.dart'; -import 'package:socks_socket/socks_socket.dart'; - -class ProxySocketSocks implements ProxySocket { - final SOCKSSocket socket; - - ProxySocketSocks(this.socket); - - @override - ProxyAddress get address => ProxyAddress(host: socket.proxyHost, port: socket.proxyPort); - - @override - Future close() => socket.close(); - - @override - Future destroy() => close(); - - @override - Future write(String data) async => socket.write(data); - - @override - StreamSubscription> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) { - return socket.listen( - (data) { - onData(Uint8List.fromList(data)); - }, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError, - ); - } -} - diff --git a/cw_core/lib/utils/proxy_wrapper.dart b/cw_core/lib/utils/proxy_wrapper.dart deleted file mode 100644 index e43f34ff1..000000000 --- a/cw_core/lib/utils/proxy_wrapper.dart +++ /dev/null @@ -1,447 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; -import 'package:cw_core/utils/proxy_logger/abstract.dart'; -import 'package:cw_core/utils/proxy_socket/abstract.dart'; -import 'package:cw_core/utils/tor/abstract.dart'; -import 'package:cw_core/utils/tor/android.dart'; -import 'package:cw_core/utils/tor/disabled.dart'; -import 'package:http/http.dart'; -import 'package:socks5_proxy/socks_client.dart'; -import 'package:http/io_client.dart' as ioc; - -class ProxyWrapper { - static final ProxyWrapper _proxyWrapper = ProxyWrapper._internal(); - static ProxyLogger? logger; - - factory ProxyWrapper() { - return _proxyWrapper; - } - - ProxyWrapper._internal(); - Future getSocksSocket(bool sslEnabled, String host, int port, {Duration? connectionTimeout}) async { - logger?.log( - uri: Uri( - scheme: sslEnabled ? "https" : "http", - host: host, - port: port, - ), - method: RequestMethod.newProxySocket, - body: Uint8List(0), - response: null, - network: requestNetwork(), - error: null - ); - return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port), connectionTimeout: connectionTimeout); - } - - RequestNetwork requestNetwork() { - return CakeTor.instance.started ? RequestNetwork.tor : RequestNetwork.clearnet; - } - - ioc.IOClient getHttpIOClient({int? portOverride, bool internal = false}) { - if (!internal) { - logger?.log( - uri: null, - method: RequestMethod.newHttpIOClient, - body: Uint8List(0), - response: null, - network: requestNetwork(), - error: null, - ); - } - // ignore: deprecated_member_use_from_same_package - final httpClient = ProxyWrapper().getHttpClient(portOverride: portOverride, internal: true); - return ioc.IOClient(httpClient); - } - - int getPort() => CakeTor.instance.port; - - @Deprecated('Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.') - HttpClient getHttpClient({int? portOverride, bool internal = false}) { - if (!internal) { - logger?.log( - uri: null, - method: RequestMethod.newProxySocket, - body: Uint8List(0), - response: null, - network: requestNetwork(), - error: null - ); - } - if (CakeTor.instance.started) { - // Assign connection factory. - final client = HttpClient(); - SocksTCPClient.assignToHttpClient(client, [ - ProxySettings( - InternetAddress.loopbackIPv4, - CakeTor.instance.port, - password: null, - ), - ]); - return client; - } else { - return HttpClient(); - } - } - - - - Future _make({ - required RequestMethod method, - required ioc.IOClient client, - required Uri uri, - required Map? headers, - String? body, - }) async { - Object? error; - Response? resp; - try { - switch (method) { - case RequestMethod.get: - resp = await client. get( - uri, - headers: headers, - ); - break; - case RequestMethod.delete: - resp = await client.delete( - uri, - headers: headers, - body: body, - ); - break; - case RequestMethod.post: - resp = await client.post( - uri, - headers: headers, - body: body, - ); - break; - case RequestMethod.put: - resp = await client.put( - uri, - headers: headers, - body: body, - ); - break; - case RequestMethod.newHttpClient: - case RequestMethod.newHttpIOClient: - case RequestMethod.newProxySocket: - throw UnimplementedError(); - } - return resp; - } catch (e) { - error = e; - rethrow; - } finally { - logger?.log( - uri: uri, - method: RequestMethod.get, - body: utf8.encode(body ?? ''), - response: resp, - network: requestNetwork(), - error: error?.toString(), - ); - } - } - - Future get({ - Map? headers, - int? portOverride, - Uri? clearnetUri, - Uri? onionUri, - }) async { - ioc.IOClient? torClient; - bool torEnabled = CakeTor.instance.started; - - if (CakeTor.instance.started) { - torEnabled = true; - } else { - torEnabled = false; - } - - // if tor is enabled, try to connect to the onion url first: - if (torEnabled) { - try { - // ignore: deprecated_member_use_from_same_package - torClient = await getHttpIOClient(portOverride: portOverride, internal: true); - } catch (_) { - rethrow; - } - - if (onionUri != null) { - try { - return await _make( - method: RequestMethod.get, - client: torClient, - uri: onionUri, - headers: headers, - ); - } catch (_) { - rethrow; - } - } - - if (clearnetUri != null) { - try { - return await _make( - method: RequestMethod.get, - client: torClient, - uri: clearnetUri, - headers: headers, - ); - } catch (_) { - rethrow; - } - } - } - - if (clearnetUri != null) { - try { - return HttpOverrides.runZoned( - () async { - return await _make( - method: RequestMethod.get, - client: ioc.IOClient(), - uri: clearnetUri, - headers: headers, - ); - }, - ); - } catch (_) { - // we weren't able to get a response: - rethrow; - } - } - - throw Exception("Unable to connect to server"); - } - - - Future post({ - Map? headers, - int? portOverride, - Uri? clearnetUri, - Uri? onionUri, - String? body, - bool allowMitmMoneroBypassSSLCheck = false, - }) async { - HttpClient? torHttpClient; - HttpClient cleatnetHttpClient = HttpClient(); - if (allowMitmMoneroBypassSSLCheck) { - cleatnetHttpClient.badCertificateCallback = - ((X509Certificate cert, String host, int port) => true); - } - - ioc.IOClient clearnetClient = ioc.IOClient(cleatnetHttpClient); - - - bool torEnabled = CakeTor.instance.started; - - if (torEnabled) { - try { - // ignore: deprecated_member_use_from_same_package - torHttpClient = await getHttpClient(portOverride: portOverride); - } catch (_) { - rethrow; - } - if (allowMitmMoneroBypassSSLCheck) { - torHttpClient.badCertificateCallback = - ((X509Certificate cert, String host, int port) => true); - } - if (onionUri != null) { - try { - return await _make( - method: RequestMethod.post, - client: ioc.IOClient(torHttpClient), - uri: onionUri, - headers: headers, - body: body, - ); - } catch (_) { - rethrow; - } - } - - if (clearnetUri != null) { - try { - return await _make( - method: RequestMethod.post, - client: ioc.IOClient(torHttpClient), - uri: clearnetUri, - headers: headers, - body: body, - ); - } catch (_) { - rethrow; - } - } - } - - if (clearnetUri != null) { - try { - return HttpOverrides.runZoned( - () async { - return await _make( - method: RequestMethod.post, - client: clearnetClient, - uri: clearnetUri, - headers: headers, - body: body, - ); - }, - ); - } catch (_) { - rethrow; - } - } - - throw Exception("Unable to connect to server"); - } - - Future put({ - Map? headers, - int? portOverride, - Uri? clearnetUri, - Uri? onionUri, - String? body, - }) async { - ioc.IOClient? torClient; - bool torEnabled = CakeTor.instance.started; - - if (torEnabled) { - try { - // ignore: deprecated_member_use_from_same_package - torClient = await getHttpIOClient(portOverride: portOverride, internal: true); - } catch (_) {} - - if (onionUri != null) { - try { - return await _make( - method: RequestMethod.put, - client: torClient!, - uri: onionUri, - headers: headers, - body: body, - ); - } catch (_) { - rethrow; - } - } - - if (clearnetUri != null) { - try { - return await _make( - method: RequestMethod.put, - client: torClient!, - uri: clearnetUri, - headers: headers, - body: body, - ); - } catch (_) { - rethrow; - } - } - } - - if (clearnetUri != null) { - try { - return HttpOverrides.runZoned( - () async { - return await _make( - method: RequestMethod.put, - client: ioc.IOClient(), - uri: clearnetUri, - headers: headers, - body: body, - ); - }, - ); - } catch (_) { - // we weren't able to get a response: - rethrow; - } - } - - throw Exception("Unable to connect to server"); - } - - Future delete({ - Map? headers, - int? portOverride, - Uri? clearnetUri, - Uri? onionUri, - }) async { - ioc.IOClient? torClient; - bool torEnabled = CakeTor.instance.started; - - if (CakeTor.instance.started) { - torEnabled = true; - } else { - torEnabled = false; - } - - // if tor is enabled, try to connect to the onion url first: - if (torEnabled) { - try { - // ignore: deprecated_member_use_from_same_package - torClient = await getHttpIOClient(portOverride: portOverride, internal: true); - } catch (_) { - rethrow; - } - - if (onionUri != null) { - try { - return await _make( - method: RequestMethod.delete, - client: torClient, - uri: onionUri, - headers: headers, - ); - } catch (_) { - rethrow; - } - } - - if (clearnetUri != null) { - try { - return await _make( - method: RequestMethod.delete, - client: torClient, - uri: clearnetUri, - headers: headers, - ); - } catch (_) { - rethrow; - } - } - } - - if (clearnetUri != null) { - try { - return HttpOverrides.runZoned( - () async { - return await _make( - method: RequestMethod.delete, - client: ioc.IOClient(), - uri: clearnetUri, - headers: headers, - ); - }, - ); - } catch (_) { - // we weren't able to get a response: - rethrow; - } - } - - throw Exception("Unable to connect to server"); - } -} - - -class CakeTor { - static final CakeTorInstance instance = CakeTorInstance.getInstance(); -} diff --git a/cw_core/lib/utils/tor/abstract.dart b/cw_core/lib/utils/tor/abstract.dart deleted file mode 100644 index aaecabc56..000000000 --- a/cw_core/lib/utils/tor/abstract.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'dart:io'; - -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/tor/android.dart'; -import 'package:cw_core/utils/tor/disabled.dart'; -import 'package:cw_core/utils/tor/tails.dart'; - -abstract class CakeTorInstance { - bool get started; - - int get port => -1; - - bool get enabled => false; - - bool get bootstrapped => false; - - Future start(); - Future stop(); - - static CakeTorInstance getInstance() { - if (Platform.isAndroid) { - return CakeTorAndroid(); - } - if (Platform.isLinux) { - try { - final os = File("/etc/os-release").readAsLinesSync(); - for (var line in os) { - if (!line.startsWith("ID=")) continue; - if (!line.contains("tails")) continue; - return CakeTorTails(); - } - } catch (e) { - printV("Failed to identify linux version - /etc/os-release missing"); - } - } - return CakeTorDisabled(); - } -} \ No newline at end of file diff --git a/cw_core/lib/utils/tor/android.dart b/cw_core/lib/utils/tor/android.dart deleted file mode 100644 index dfc1bfbe4..000000000 --- a/cw_core/lib/utils/tor/android.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/tor/abstract.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:path/path.dart' as p; -import 'package:tor_binary/tor_binary_platform_interface.dart'; - -class CakeTorAndroid implements CakeTorInstance { - @override - bool get bootstrapped => _proc != null; - - @override - bool get enabled => _proc != null; - - @override - int get port => 42142; - - @override - Future start() async { - await _runEmbeddedTor(); - } - - @override - bool get started => _proc != null; - - @override - Future stop() async { - _proc?.kill(); - await _proc?.exitCode; - _proc = null; - } - - static Process? _proc; - - Future _runEmbeddedTor() async { - final dir = await getApplicationCacheDirectory(); - - final torBinPath = p.join((await TorBinaryPlatform.instance.getBinaryPath())!, "libtor.so"); - printV("torPath: $torBinPath"); - - if (started) { - printV("Proxy is running"); - return; - } - - printV("Starting embedded tor"); - printV("app docs: $dir"); - final torrc = """ -SocksPort $port -Log notice file ${p.join(dir.path, "tor.log")} -RunAsDaemon 0 -DataDirectory ${p.join(dir.path, "tor-data")} -"""; - final torrcPath = p.join(dir.absolute.path, "torrc"); - File(torrcPath).writeAsStringSync(torrc); - - if (_proc != null) { - try { - _proc?.kill(); - await _proc?.exitCode; - _proc = null; - } catch (e) { - printV(e); - } - } - printV("path: $torBinPath -f $torrcPath"); - _proc = await Process.start(torBinPath, ["-f", torrcPath]); - _proc?.stdout.transform(utf8.decoder).forEach(printV); - _proc?.stderr.transform(utf8.decoder).forEach(printV); - } -} \ No newline at end of file diff --git a/cw_core/lib/utils/tor/disabled.dart b/cw_core/lib/utils/tor/disabled.dart deleted file mode 100644 index 8bd3d837e..000000000 --- a/cw_core/lib/utils/tor/disabled.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:cw_core/utils/tor/abstract.dart'; - -class CakeTorDisabled implements CakeTorInstance { - @override - bool get bootstrapped => false; - - @override - bool get enabled => false; - - @override - int get port => -1; - - @override - Future start() => throw UnimplementedError(); - - @override - bool get started => false; - - @override - Future stop() => throw UnimplementedError(); -} \ No newline at end of file diff --git a/cw_core/lib/utils/tor/tails.dart b/cw_core/lib/utils/tor/tails.dart deleted file mode 100644 index c37ee72aa..000000000 --- a/cw_core/lib/utils/tor/tails.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:cw_core/utils/tor/abstract.dart'; - -class CakeTorTails implements CakeTorInstance { - @override - bool get bootstrapped => true; - - @override - bool get enabled => true; - - @override - int get port => 9150; - - @override - Future start() async {} - - @override - bool get started => true; - - @override - Future stop() async {} -} \ No newline at end of file diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index d7bfdbe2a..265eaa9bc 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -26,18 +26,18 @@ packages: dependency: transitive description: name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.6.0" asn1lib: dependency: transitive description: name: asn1lib - sha256: "1c296cd268f486cabcc3930e9b93a8133169305f18d722916e675959a88f6d2c" + sha256: "4bae5ae63e6d6dd17c4aac8086f3dec26c0236f6a0f03416c6c19d830c367cf5" url: "https://pub.dev" source: hosted - version: "1.5.9" + version: "1.5.8" async: dependency: transitive description: @@ -67,50 +67,50 @@ packages: dependency: transitive description: name: build - sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.1" build_config: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.2" build_resolvers: dependency: "direct dev" description: name: build_resolvers - sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.3.2" built_collection: dependency: transitive description: @@ -123,10 +123,10 @@ packages: dependency: transitive description: name: built_value - sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27" + sha256: "8b158ab94ec6913e480dc3f752418348b5ae099eb75868b5f4775f0572999c61" url: "https://pub.dev" source: hosted - version: "8.10.1" + version: "8.9.4" cake_backup: dependency: "direct main" description: @@ -212,10 +212,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" url: "https://pub.dev" source: hosted - version: "2.3.8" + version: "2.3.7" decimal: dependency: "direct main" description: @@ -326,10 +326,10 @@ packages: dependency: "direct main" description: name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" http_multi_server: dependency: transitive description: @@ -342,10 +342,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.1.2" + version: "4.0.2" intl: dependency: "direct main" description: @@ -462,10 +462,10 @@ packages: dependency: "direct dev" description: name: mobx_codegen - sha256: e0abbbc651a69550440f6b65c99ec222a1e2a4afd7baec8ba0f3088c7ca582a8 + sha256: "990da80722f7d7c0017dec92040b31545d625b15d40204c36a1e63d167c73cdc" url: "https://pub.dev" source: hosted - version: "2.7.1" + version: "2.7.0" nested: dependency: transitive description: @@ -479,7 +479,7 @@ packages: description: path: "." ref: cake-update-v2 - resolved-ref: "096865a8c6b89c260beadfec04f7e184c40a3273" + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2" url: "https://github.com/cake-tech/on_chain.git" source: git version: "3.7.0" @@ -487,10 +487,10 @@ packages: dependency: transitive description: name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.1" path: dependency: transitive description: @@ -511,10 +511,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.2.15" path_provider_foundation: dependency: transitive description: @@ -583,26 +583,26 @@ packages: dependency: transitive description: name: provider - sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.1.2" pub_semver: dependency: transitive description: name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.5" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.4.0" rational: dependency: transitive description: @@ -615,18 +615,18 @@ packages: dependency: transitive description: name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "2.0.1" sky_engine: dependency: transitive description: flutter @@ -635,21 +635,11 @@ packages: socks5_proxy: dependency: "direct main" description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: "direct main" - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: @@ -726,19 +716,10 @@ packages: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" - tor_binary: - dependency: "direct main" - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" + version: "1.0.2" tuple: dependency: transitive description: @@ -799,18 +780,18 @@ packages: dependency: transitive description: name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" xdg_directories: dependency: transitive description: @@ -828,5 +809,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.27.4" diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 07f87475a..9b38b61a7 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -25,29 +25,22 @@ dependencies: url: https://github.com/cake-tech/cake_backup.git ref: main version: 1.0.0 - socks5_proxy: - git: - url: https://github.com/LacticWhale/socks_dart - ref: 27ad7c2efae8d7460325c74b90f660085cbd0685 + socks5_proxy: ^1.0.4 unorm_dart: ^0.3.0 on_chain: git: url: https://github.com/cake-tech/on_chain.git ref: cake-update-v2 - socks_socket: - git: - url: https://github.com/sneurlax/socks_socket - ref: e6232c53c1595469931ababa878759a067c02e94 - tor_binary: - git: - url: https://github.com/MrCyjaneK/flutter-tor_binary - ref: cb811c610871a9517d47134b87c2f590c15c96c5 +# tor: +# git: +# url: https://github.com/cake-tech/tor.git +# ref: main dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 - build_resolvers: ^2.4.4 + build_runner: ^2.4.7 + build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 diff --git a/cw_decred/lib/wallet.dart b/cw_decred/lib/wallet.dart index 97aee775d..ac70a4aaa 100644 --- a/cw_decred/lib/wallet.dart +++ b/cw_decred/lib/wallet.dart @@ -5,8 +5,6 @@ import 'package:path/path.dart' as p; import 'package:cw_core/exceptions.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:cw_decred/amount_format.dart'; import 'package:cw_decred/pending_transaction.dart'; import 'package:cw_decred/transaction_credentials.dart'; @@ -309,10 +307,9 @@ abstract class DecredWalletBase persistantPeer = addr; await _libwallet.closeWallet(walletInfo.name); final network = isTestnet ? "testnet" : "mainnet"; - final dirPath = await pathForWalletDir(name: walletInfo.name, type: WalletType.decred); final config = { "name": walletInfo.name, - "datadir": dirPath, + "datadir": walletInfo.dirPath, "net": network, "unsyncedaddrs": true, }; @@ -608,22 +605,22 @@ abstract class DecredWalletBase final sourceDir = Directory(currentDirPath); final targetDir = Directory(newDirPath); - + if (!targetDir.existsSync()) { await targetDir.create(recursive: true); } - + await for (final entity in sourceDir.list(recursive: true)) { - final relativePath = entity.path.substring(sourceDir.path.length + 1); + final relativePath = entity.path.substring(sourceDir.path.length+1); final targetPath = p.join(targetDir.path, relativePath); - + if (entity is File) { await entity.rename(targetPath); } else if (entity is Directory) { await Directory(targetPath).create(recursive: true); } } - + await sourceDir.delete(recursive: true); } diff --git a/cw_decred/lib/wallet_service.dart b/cw_decred/lib/wallet_service.dart index 93c708886..e2313904e 100644 --- a/cw_decred/lib/wallet_service.dart +++ b/cw_decred/lib/wallet_service.dart @@ -8,7 +8,6 @@ import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:path/path.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -58,93 +57,42 @@ class DecredWalletService extends WalletService< @override Future create(DecredNewWalletCredentials credentials, {bool? isTestnet}) async { await this.init(); - final dirPath = await pathForWalletDir(name: credentials.walletInfo!.name, type: getType()); - final network = isTestnet == true ? testnet : mainnet; final config = { "name": credentials.walletInfo!.name, - "datadir": dirPath, + "datadir": credentials.walletInfo!.dirPath, "pass": credentials.password!, - "net": network, + "net": isTestnet == true ? testnet : mainnet, "unsyncedaddrs": true, }; await libwallet!.createWallet(jsonEncode(config)); final di = DerivationInfo( derivationPath: isTestnet == true ? seedRestorePathTestnet : seedRestorePath); credentials.walletInfo!.derivationInfo = di; - credentials.walletInfo!.network = network; - // ios will move our wallet directory when updating. Since we must - // recalculate the new path every time we open the wallet, ensure this path - // is not used. An older wallet will have a directory here which is a - // condition for moving the wallet when opening, so this must be kept blank - // going forward. - credentials.walletInfo!.dirPath = ""; - credentials.walletInfo!.path = ""; final wallet = DecredWallet(credentials.walletInfo!, credentials.password!, this.unspentCoinsInfoSource, libwallet!, closeLibwallet); await wallet.init(); return wallet; } - void copyDirectorySync(Directory source, Directory destination) { - /// create destination folder if not exist - if (!destination.existsSync()) { - destination.createSync(recursive: true); - } - - /// get all files from source (recursive: false is important here) - source.listSync(recursive: false).forEach((entity) { - final newPath = destination.path + Platform.pathSeparator + basename(entity.path); - if (entity is File) { - entity.rename(newPath); - } else if (entity is Directory) { - copyDirectorySync(entity, Directory(newPath)); - } - }); - } - - Future moveWallet(String fromPath, String toPath) async { - final oldWalletDir = new Directory(fromPath); - final newWalletDir = new Directory(toPath); - copyDirectorySync(oldWalletDir, newWalletDir); - // It would be ideal to delete the old directory here, but ios will error - // sometimes with "OS Error: No such file or directory, errno = 2" even - // after checking if it exists. - } - @override Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; - if (walletInfo.network == null || walletInfo.network == "") { - walletInfo.network = walletInfo.derivationInfo?.derivationPath == seedRestorePathTestnet || - walletInfo.derivationInfo?.derivationPath == pubkeyRestorePathTestnet - ? testnet - : mainnet; - } + final network = walletInfo.derivationInfo?.derivationPath == seedRestorePathTestnet || + walletInfo.derivationInfo?.derivationPath == pubkeyRestorePathTestnet + ? testnet + : mainnet; await this.init(); - - // Cake wallet version 4.27.0 and earlier gave a wallet dir that did not - // match the name. Move those to the correct place. - final dirPath = await pathForWalletDir(name: name, type: getType()); - if (walletInfo.path != "") { - // On ios the stored dir no longer exists. We can only trust the basename. - // dirPath may already be updated and lost the basename, so look at path. - final randomBasename = basename(walletInfo.path); - final oldDir = await pathForWalletDir(name: randomBasename, type: getType()); - if (oldDir != dirPath) { - await this.moveWallet(oldDir, dirPath); - } - // Clear the path so this does not trigger again. - walletInfo.dirPath = ""; - walletInfo.path = ""; - await walletInfo.save(); + final walletDirExists = Directory(walletInfo.dirPath).existsSync(); + if (!walletDirExists) { + walletInfo.dirPath = await pathForWalletDir(name: name, type: getType()); } final config = { - "name": name, - "datadir": dirPath, - "net": walletInfo.network, + "name": walletInfo.name, + "datadir": walletInfo.dirPath, + "net": network, "unsyncedaddrs": true, }; await libwallet!.loadWallet(jsonEncode(config)); @@ -179,11 +127,12 @@ class DecredWalletService extends WalletService< await currentWallet.renameWalletFiles(newName); + final newDirPath = await pathForWalletDir(name: newName, type: getType()); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); newWalletInfo.name = newName; - newWalletInfo.dirPath = ""; - newWalletInfo.path = ""; + newWalletInfo.dirPath = newDirPath; + newWalletInfo.network = network; await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); } @@ -192,23 +141,18 @@ class DecredWalletService extends WalletService< Future restoreFromSeed(DecredRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { await this.init(); - final network = isTestnet == true ? testnet : mainnet; - final dirPath = await pathForWalletDir(name: credentials.walletInfo!.name, type: getType()); final config = { "name": credentials.walletInfo!.name, - "datadir": dirPath, + "datadir": credentials.walletInfo!.dirPath, "pass": credentials.password!, "mnemonic": credentials.mnemonic, - "net": network, + "net": isTestnet == true ? testnet : mainnet, "unsyncedaddrs": true, }; await libwallet!.createWallet(jsonEncode(config)); final di = DerivationInfo( derivationPath: isTestnet == true ? seedRestorePathTestnet : seedRestorePath); credentials.walletInfo!.derivationInfo = di; - credentials.walletInfo!.network = network; - credentials.walletInfo!.dirPath = ""; - credentials.walletInfo!.path = ""; final wallet = DecredWallet(credentials.walletInfo!, credentials.password!, this.unspentCoinsInfoSource, libwallet!, closeLibwallet); await wallet.init(); @@ -221,22 +165,17 @@ class DecredWalletService extends WalletService< Future restoreFromKeys(DecredRestoreWalletFromPubkeyCredentials credentials, {bool? isTestnet}) async { await this.init(); - final network = isTestnet == true ? testnet : mainnet; - final dirPath = await pathForWalletDir(name: credentials.walletInfo!.name, type: getType()); final config = { "name": credentials.walletInfo!.name, - "datadir": dirPath, + "datadir": credentials.walletInfo!.dirPath, "pubkey": credentials.pubkey, - "net": network, + "net": isTestnet == true ? testnet : mainnet, "unsyncedaddrs": true, }; await libwallet!.createWatchOnlyWallet(jsonEncode(config)); final di = DerivationInfo( derivationPath: isTestnet == true ? pubkeyRestorePathTestnet : pubkeyRestorePath); credentials.walletInfo!.derivationInfo = di; - credentials.walletInfo!.network = network; - credentials.walletInfo!.dirPath = ""; - credentials.walletInfo!.path = ""; final wallet = DecredWallet(credentials.walletInfo!, credentials.password!, this.unspentCoinsInfoSource, libwallet!, closeLibwallet); await wallet.init(); diff --git a/cw_decred/pubspec.lock b/cw_decred/pubspec.lock index f7a5f335d..007d9cfb2 100644 --- a/cw_decred/pubspec.lock +++ b/cw_decred/pubspec.lock @@ -91,26 +91,26 @@ packages: dependency: "direct dev" description: name: build_resolvers - sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.3.2" built_collection: dependency: transitive description: @@ -666,21 +666,11 @@ packages: socks5_proxy: dependency: transitive description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: transitive - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: @@ -761,15 +751,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" - tor_binary: - dependency: transitive - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" tuple: dependency: transitive description: @@ -867,5 +848,5 @@ packages: source: hosted version: "2.2.2" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.27.4" diff --git a/cw_decred/pubspec.yaml b/cw_decred/pubspec.yaml index 989831a89..fcb2ac5ec 100644 --- a/cw_decred/pubspec.yaml +++ b/cw_decred/pubspec.yaml @@ -19,8 +19,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 - build_resolvers: ^2.4.4 + build_runner: ^2.1.11 + build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 ffigen: ^16.1.0 diff --git a/cw_ethereum/lib/default_ethereum_erc20_tokens.dart b/cw_ethereum/lib/default_ethereum_erc20_tokens.dart index 630424967..8381744d6 100644 --- a/cw_ethereum/lib/default_ethereum_erc20_tokens.dart +++ b/cw_ethereum/lib/default_ethereum_erc20_tokens.dart @@ -18,7 +18,7 @@ class DefaultEthereumErc20Tokens { enabled: true, ), Erc20Token( - name: "Decentralized Euro", + name: "Digital Euro", symbol: "DEURO", contractAddress: "0xbA3f535bbCcCcA2A154b573Ca6c5A49BAAE0a3ea", decimal: 18, diff --git a/cw_ethereum/lib/deuro/deuro_savings.dart b/cw_ethereum/lib/deuro/deuro_savings.dart deleted file mode 100644 index bce05905c..000000000 --- a/cw_ethereum/lib/deuro/deuro_savings.dart +++ /dev/null @@ -1,170 +0,0 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_ethereum/deuro/deuro_savings_contract.dart'; -import 'package:cw_ethereum/ethereum_wallet.dart'; -import 'package:cw_evm/contract/erc20.dart'; -import 'package:cw_evm/evm_chain_exceptions.dart'; -import 'package:cw_evm/evm_chain_transaction_priority.dart'; -import 'package:cw_evm/pending_evm_chain_transaction.dart'; -import 'package:web3dart/crypto.dart'; -import 'package:web3dart/web3dart.dart'; - -const String savingsGatewayAddress = "0x073493d73258C4BEb6542e8dd3e1b2891C972303"; - -const String dEuroAddress = "0xbA3f535bbCcCcA2A154b573Ca6c5A49BAAE0a3ea"; -const String frontendCode = "0x00000000000000000000000000000000000000000043616b652057616c6c6574"; - -class DEuro { - final SavingsGateway _savingsGateway; - final ERC20 _dEuro; - final EthereumWallet _wallet; - - DEuro(EthereumWallet wallet) - : _wallet = wallet, - _savingsGateway = _getSavingsGateway(wallet.getWeb3Client()!), - _dEuro = _getDEuroToken(wallet.getWeb3Client()!); - - static SavingsGateway _getSavingsGateway(Web3Client client) => SavingsGateway( - address: EthereumAddress.fromHex(savingsGatewayAddress), - client: client, - ); - - static ERC20 _getDEuroToken(Web3Client client) => ERC20( - address: EthereumAddress.fromHex(dEuroAddress), - client: client, - ); - - EthereumAddress get _address => EthereumAddress.fromHex(_wallet.walletAddresses.primaryAddress); - - Future get savingsBalance async => - (await _savingsGateway.savings(accountOwner: _address)).saved; - - Future get accruedInterest => _savingsGateway.accruedInterest(accountOwner: _address); - - Future get interestRate => _savingsGateway.currentRatePPM(); - - Future get approvedBalance => _dEuro.allowance(_address, _savingsGateway.self.address); - - Future _checkEthBalanceForGasFees(EVMChainTransactionPriority priority) async { - final ethBalance = await _wallet.getWeb3Client()!.getBalance(_address); - final currentBalance = ethBalance.getInWei; - - final gasFeesModel = await _wallet.calculateActualEstimatedFeeForCreateTransaction( - amount: BigInt.zero, - contractAddress: _savingsGateway.self.address.hexEip55, - receivingAddressHex: _savingsGateway.self.address.hexEip55, - priority: priority, - data: _savingsGateway.self.abi.functions[17] - .encodeCall([BigInt.zero, hexToBytes(frontendCode)]), - ); - - final estimatedGasFee = BigInt.from(gasFeesModel.estimatedGasFee); - final requiredBalance = estimatedGasFee; - - if (currentBalance < requiredBalance) { - throw DeuroGasFeeException( - requiredGasFee: requiredBalance, - currentBalance: currentBalance, - ); - } - } - - Future depositSavings( - BigInt amount, EVMChainTransactionPriority priority) async { - try { - await _checkEthBalanceForGasFees(priority); - - final signedTransaction = await _savingsGateway.save( - (amount: amount, frontendCode: hexToBytes(frontendCode)), - credentials: _wallet.evmChainPrivateKey, - ); - - final fee = await _wallet.calculateActualEstimatedFeeForCreateTransaction( - amount: amount, - contractAddress: _savingsGateway.self.address.hexEip55, - receivingAddressHex: _savingsGateway.self.address.hexEip55, - priority: priority, - data: _savingsGateway.self.abi.functions[17].encodeCall([amount, hexToBytes(frontendCode)]), - ); - - final sendTransaction = () => _wallet.getWeb3Client()!.sendRawTransaction(signedTransaction); - - return PendingEVMChainTransaction( - sendTransaction: sendTransaction, - signedTransaction: signedTransaction, - fee: BigInt.from(fee.estimatedGasFee), - amount: amount.toString(), - exponent: 18, - ); - } catch (e) { - if (e.toString().contains('insufficient funds for gas')) { - final ethBalance = await _wallet.getWeb3Client()!.getBalance(_address); - throw DeuroGasFeeException( - currentBalance: ethBalance.getInWei, - ); - } - rethrow; - } - } - - Future withdrawSavings( - BigInt amount, EVMChainTransactionPriority priority) async { - try { - await _checkEthBalanceForGasFees(priority); - - final signedTransaction = await _savingsGateway.withdraw( - (target: _address, amount: amount, frontendCode: hexToBytes(frontendCode)), - credentials: _wallet.evmChainPrivateKey, - ); - - final fee = await _wallet.calculateActualEstimatedFeeForCreateTransaction( - amount: amount, - contractAddress: _savingsGateway.self.address.hexEip55, - receivingAddressHex: _savingsGateway.self.address.hexEip55, - priority: priority, - data: _savingsGateway.self.abi.functions[17].encodeCall([amount, hexToBytes(frontendCode)]), - ); - - final sendTransaction = () => _wallet.getWeb3Client()!.sendRawTransaction(signedTransaction); - - return PendingEVMChainTransaction( - sendTransaction: sendTransaction, - signedTransaction: signedTransaction, - fee: BigInt.from(fee.estimatedGasFee), - amount: amount.toString(), - exponent: 18); - } catch (e) { - if (e.toString().contains('insufficient funds for gas')) { - final ethBalance = await _wallet.getWeb3Client()!.getBalance(_address); - throw DeuroGasFeeException( - currentBalance: ethBalance.getInWei, - ); - } - rethrow; - } - } - - // Set an infinite approval to save gas in the future - Future enableSavings(EVMChainTransactionPriority priority) async { - try { - await _checkEthBalanceForGasFees(priority); - - return (await _wallet.createApprovalTransaction( - BigInt.parse( - 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - radix: 16, - ), - _savingsGateway.self.address.hexEip55, - CryptoCurrency.deuro, - priority, - )) as PendingEVMChainTransaction; - } catch (e) { - if (e.toString().contains('insufficient funds for gas')) { - final ethBalance = await _wallet.getWeb3Client()!.getBalance(_address); - throw DeuroGasFeeException( - currentBalance: ethBalance.getInWei, - ); - } - rethrow; - } - } -} diff --git a/cw_ethereum/lib/deuro/deuro_savings_contract.dart b/cw_ethereum/lib/deuro/deuro_savings_contract.dart deleted file mode 100644 index ca2eb5dcc..000000000 --- a/cw_ethereum/lib/deuro/deuro_savings_contract.dart +++ /dev/null @@ -1,543 +0,0 @@ -// ignore_for_file: type=lint -// ignore_for_file: unused_local_variable, unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:web3dart/web3dart.dart' as _i1; -import 'dart:typed_data' as _i2; - -final _contractAbi = _i1.ContractAbi.fromJson( - '[{"inputs":[{"internalType":"contract IDecentralizedEURO","name":"deuro_","type":"address"},{"internalType":"uint24","name":"initialRatePPM","type":"uint24"},{"internalType":"address","name":"gateway_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ChangeNotReady","type":"error"},{"inputs":[],"name":"ModuleDisabled","type":"error"},{"inputs":[],"name":"NoPendingChange","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"}],"name":"InterestCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"newRate","type":"uint24"}],"name":"RateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"uint24","name":"nextRate","type":"uint24"},{"indexed":false,"internalType":"uint40","name":"nextChange","type":"uint40"}],"name":"RateProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint192","name":"amount","type":"uint192"}],"name":"Saved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint192","name":"amount","type":"uint192"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"GATEWAY","outputs":[{"internalType":"contract IFrontendGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountOwner","type":"address"}],"name":"accruedInterest","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountOwner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"accruedInterest","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint192","name":"targetAmount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"adjust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"targetAmount","type":"uint192"}],"name":"adjust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"applyChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint192","name":"saved","type":"uint192"},{"internalType":"uint64","name":"ticks","type":"uint64"}],"internalType":"struct Savings.Account","name":"account","type":"tuple"},{"internalType":"uint64","name":"ticks","type":"uint64"}],"name":"calculateInterest","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRatePPM","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTicks","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deuro","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"equity","outputs":[{"internalType":"contract IReserve","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextChange","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextRatePPM","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"newRatePPM_","type":"uint24"},{"internalType":"address[]","name":"helpers","type":"address[]"}],"name":"proposeChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"refreshBalance","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refreshMyBalance","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"amount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"amount","type":"uint192"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"savings","outputs":[{"internalType":"uint192","name":"saved","type":"uint192"},{"internalType":"uint64","name":"ticks","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ticks","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]', - 'SavingsGateway', -); - -class SavingsGateway extends _i1.GeneratedContract { - SavingsGateway({ - required _i1.EthereumAddress address, - required _i1.Web3Client client, - int? chainId, - }) : super( - _i1.DeployedContract( - _contractAbi, - address, - ), - client, - chainId, - ); - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future<_i1.EthereumAddress> GATEWAY({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[1]; - assert(checkSignature(function, '338c5371')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as _i1.EthereumAddress); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future accruedInterest({ - required _i1.EthereumAddress accountOwner, - _i1.BlockNum? atBlock, - }) async { - final function = self.abi.functions[2]; - assert(checkSignature(function, '77267ec3')); - final params = [accountOwner]; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future accruedInterest$2( - ({_i1.EthereumAddress accountOwner, BigInt timestamp}) args, { - _i1.BlockNum? atBlock, - }) async { - final function = self.abi.functions[3]; - assert(checkSignature(function, 'a696399d')); - final params = [ - args.accountOwner, - args.timestamp, - ]; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [transaction] parameter can be used to override parameters - /// like the gas price, nonce and max gas. The `data` and `to` fields will be - /// set by the contract. - Future adjust( - ({BigInt targetAmount, _i2.Uint8List frontendCode}) args, { - required _i1.Credentials credentials, - _i1.Transaction? transaction, - }) async { - final function = self.abi.functions[4]; - assert(checkSignature(function, '753ef93c')); - final params = [ - args.targetAmount, - args.frontendCode, - ]; - return write( - credentials, - transaction, - function, - params, - ); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future calculateInterest( - ({dynamic account, BigInt ticks}) args, { - _i1.BlockNum? atBlock, - }) async { - final function = self.abi.functions[7]; - assert(checkSignature(function, '7915ce20')); - final params = [ - args.account, - args.ticks, - ]; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future currentRatePPM({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[8]; - assert(checkSignature(function, '06a7b376')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future currentTicks({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[9]; - assert(checkSignature(function, 'b079f163')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future<_i1.EthereumAddress> deuro({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[10]; - assert(checkSignature(function, '82b8eaf5')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as _i1.EthereumAddress); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future<_i1.EthereumAddress> equity({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[11]; - assert(checkSignature(function, '91a0ac6a')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as _i1.EthereumAddress); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future nextChange({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[12]; - assert(checkSignature(function, 'b6f83c17')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future nextRatePPM({_i1.BlockNum? atBlock}) async { - final function = self.abi.functions[13]; - assert(checkSignature(function, '2e4b20ab')); - final params = []; - final response = await read( - function, - params, - atBlock, - ); - return (response[0] as BigInt); - } - - /// The optional [transaction] parameter can be used to override parameters - /// like the gas price, nonce and max gas. The `data` and `to` fields will be - /// set by the contract. - Future refreshBalance( - ({_i1.EthereumAddress owner}) args, { - required _i1.Credentials credentials, - _i1.Transaction? transaction, - }) async { - final function = self.abi.functions[15]; - assert(checkSignature(function, 'b77cd1c7')); - final params = [args.owner]; - return write( - credentials, - transaction, - function, - params, - ); - } - - /// The optional [transaction] parameter can be used to override parameters - /// like the gas price, nonce and max gas. The `data` and `to` fields will be - /// set by the contract. - Future refreshMyBalance({ - required _i1.Credentials credentials, - _i1.Transaction? transaction, - }) async { - final function = self.abi.functions[16]; - assert(checkSignature(function, '85bd12d1')); - final params = []; - return write( - credentials, - transaction, - function, - params, - ); - } - - /// The optional [transaction] parameter can be used to override parameters - /// like the gas price, nonce and max gas. The `data` and `to` fields will be - /// set by the contract. - Future<_i2.Uint8List> save( - ({BigInt amount, _i2.Uint8List frontendCode}) args, { - required _i1.Credentials credentials, - _i1.Transaction? transaction, - }) async { - final function = self.abi.functions[17]; - assert(checkSignature(function, '9e2363dc')); - final params = [ - args.amount, - args.frontendCode, - ]; - return writeRaw( - credentials, - transaction, - function, - params, - ); - } - - /// The optional [transaction] parameter can be used to override parameters - /// like the gas price, nonce and max gas. The `data` and `to` fields will be - /// set by the contract. - Future<_i2.Uint8List> saveTo( - ({ - _i1.EthereumAddress owner, - BigInt amount, - _i2.Uint8List frontendCode - }) args, { - required _i1.Credentials credentials, - _i1.Transaction? transaction, - }) async { - final function = self.abi.functions[19]; - assert(checkSignature(function, 'cbcf9676')); - final params = [ - args.owner, - args.amount, - args.frontendCode, - ]; - return writeRaw( - credentials, - transaction, - function, - params, - ); - } - - /// The optional [atBlock] parameter can be used to view historical data. When - /// set, the function will be evaluated in the specified block. By default, the - /// latest on-chain block will be used. - Future savings({ - required _i1.EthereumAddress accountOwner, - _i1.BlockNum? atBlock, - }) async { - final function = self.abi.functions[21]; - assert(checkSignature(function, '1f7cdd5f')); - final params = [accountOwner]; - final response = await read( - function, - params, - atBlock, - ); - return Savings(response); - } - - /// The optional [transaction] parameter can be used to override parameters - /// like the gas price, nonce and max gas. The `data` and `to` fields will be - /// set by the contract. - Future<_i2.Uint8List> withdraw( - ({ - _i1.EthereumAddress target, - BigInt amount, - _i2.Uint8List frontendCode - }) args, { - required _i1.Credentials credentials, - _i1.Transaction? transaction, - }) async { - final function = self.abi.functions[24]; - assert(checkSignature(function, '829a0476')); - final params = [ - args.target, - args.amount, - args.frontendCode, - ]; - return writeRaw( - credentials, - transaction, - function, - params, - ); - } - - /// Returns a live stream of all InterestCollected events emitted by this contract. - Stream interestCollectedEvents({ - _i1.BlockNum? fromBlock, - _i1.BlockNum? toBlock, - }) { - final event = self.event('InterestCollected'); - final filter = _i1.FilterOptions.events( - contract: self, - event: event, - fromBlock: fromBlock, - toBlock: toBlock, - ); - return client.events(filter).map((_i1.FilterEvent result) { - final decoded = event.decodeResults( - result.topics!, - result.data!, - ); - return InterestCollected( - decoded, - result, - ); - }); - } - - /// Returns a live stream of all RateChanged events emitted by this contract. - Stream rateChangedEvents({ - _i1.BlockNum? fromBlock, - _i1.BlockNum? toBlock, - }) { - final event = self.event('RateChanged'); - final filter = _i1.FilterOptions.events( - contract: self, - event: event, - fromBlock: fromBlock, - toBlock: toBlock, - ); - return client.events(filter).map((_i1.FilterEvent result) { - final decoded = event.decodeResults( - result.topics!, - result.data!, - ); - return RateChanged( - decoded, - result, - ); - }); - } - - /// Returns a live stream of all RateProposed events emitted by this contract. - Stream rateProposedEvents({ - _i1.BlockNum? fromBlock, - _i1.BlockNum? toBlock, - }) { - final event = self.event('RateProposed'); - final filter = _i1.FilterOptions.events( - contract: self, - event: event, - fromBlock: fromBlock, - toBlock: toBlock, - ); - return client.events(filter).map((_i1.FilterEvent result) { - final decoded = event.decodeResults( - result.topics!, - result.data!, - ); - return RateProposed( - decoded, - result, - ); - }); - } - - /// Returns a live stream of all Saved events emitted by this contract. - Stream savedEvents({ - _i1.BlockNum? fromBlock, - _i1.BlockNum? toBlock, - }) { - final event = self.event('Saved'); - final filter = _i1.FilterOptions.events( - contract: self, - event: event, - fromBlock: fromBlock, - toBlock: toBlock, - ); - return client.events(filter).map((_i1.FilterEvent result) { - final decoded = event.decodeResults( - result.topics!, - result.data!, - ); - return Saved( - decoded, - result, - ); - }); - } - - /// Returns a live stream of all Withdrawn events emitted by this contract. - Stream withdrawnEvents({ - _i1.BlockNum? fromBlock, - _i1.BlockNum? toBlock, - }) { - final event = self.event('Withdrawn'); - final filter = _i1.FilterOptions.events( - contract: self, - event: event, - fromBlock: fromBlock, - toBlock: toBlock, - ); - return client.events(filter).map((_i1.FilterEvent result) { - final decoded = event.decodeResults( - result.topics!, - result.data!, - ); - return Withdrawn( - decoded, - result, - ); - }); - } -} - -class Savings { - Savings(List response) - : saved = (response[0] as BigInt), - ticks = (response[1] as BigInt); - - final BigInt saved; - - final BigInt ticks; -} - -class InterestCollected { - InterestCollected( - List response, - this.event, - ) : account = (response[0] as _i1.EthereumAddress), - interest = (response[1] as BigInt); - - final _i1.EthereumAddress account; - - final BigInt interest; - - final _i1.FilterEvent event; -} - -class RateChanged { - RateChanged( - List response, - this.event, - ) : newRate = (response[0] as BigInt); - - final BigInt newRate; - - final _i1.FilterEvent event; -} - -class RateProposed { - RateProposed( - List response, - this.event, - ) : who = (response[0] as _i1.EthereumAddress), - nextRate = (response[1] as BigInt), - nextChange = (response[2] as BigInt); - - final _i1.EthereumAddress who; - - final BigInt nextRate; - - final BigInt nextChange; - - final _i1.FilterEvent event; -} - -class Saved { - Saved( - List response, - this.event, - ) : account = (response[0] as _i1.EthereumAddress), - amount = (response[1] as BigInt); - - final _i1.EthereumAddress account; - - final BigInt amount; - - final _i1.FilterEvent event; -} - -class Withdrawn { - Withdrawn( - List response, - this.event, - ) : account = (response[0] as _i1.EthereumAddress), - amount = (response[1] as BigInt); - - final _i1.EthereumAddress account; - - final BigInt amount; - - final _i1.FilterEvent event; -} diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 259e7d11d..9d50fdd5b 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -19,8 +19,7 @@ class EthereumClient extends EVMChainClient { Future> fetchTransactions(String address, {String? contractAddress}) async { try { - final response = await client.get(Uri.https("api.etherscan.io", "/v2/api", { - "chainid": "$chainId", + final response = await httpClient.get(Uri.https("api.etherscan.io", "/api", { "module": "account", "action": contractAddress != null ? "tokentx" : "txlist", if (contractAddress != null) "contractaddress": contractAddress, @@ -51,8 +50,7 @@ class EthereumClient extends EVMChainClient { @override Future> fetchInternalTransactions(String address) async { try { - final response = await client.get(Uri.https("api.etherscan.io", "/v2/api", { - "chainid": "$chainId", + final response = await httpClient.get(Uri.https("api.etherscan.io", "/api", { "module": "account", "action": "txlistinternal", "address": address, diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index c22be3cb2..7cc140c5a 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -31,14 +31,11 @@ class EthereumWallet extends EVMChainWallet { }) : super(nativeCurrency: CryptoCurrency.eth); @override - void addInitialTokens([bool isMigration = false]) { + void addInitialTokens() { final initialErc20Tokens = DefaultEthereumErc20Tokens().initialErc20Tokens; - for (final token in initialErc20Tokens) { - if (!evmChainErc20TokensBox.containsKey(token.contractAddress)) { - if (isMigration) token.enabled = false; - evmChainErc20TokensBox.put(token.contractAddress, token); - } + for (var token in initialErc20Tokens) { + evmChainErc20TokensBox.put(token.contractAddress, token); } } diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 06ba07bfc..858416055 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -53,7 +53,6 @@ class EthereumWalletService extends EVMChainWalletService { ); await wallet.init(); - wallet.addInitialTokens(true); await wallet.save(); saveBackup(name); return wallet; diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 1da1e3b3b..462e1d77e 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -6,7 +6,7 @@ author: Cake Wallet homepage: https://cakewallet.com environment: - sdk: ^3.5.0 + sdk: '>=2.18.2 <3.0.0' flutter: ">=1.17.0" dependencies: @@ -29,7 +29,7 @@ dependency_overrides: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 + build_runner: ^2.4.7 flutter: # assets: diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index 1fecc9c1e..7e6caf374 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -5,7 +5,6 @@ import 'dart:developer'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/node.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_evm/evm_chain_transaction_model.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; import 'package:cw_evm/evm_erc20_balance.dart'; @@ -13,12 +12,13 @@ import 'package:cw_evm/pending_evm_chain_transaction.dart'; import 'package:cw_evm/.secrets.g.dart' as secrets; import 'package:flutter/foundation.dart'; import 'package:hex/hex.dart' as hex; +import 'package:http/http.dart'; import 'package:web3dart/web3dart.dart'; import 'contract/erc20.dart'; abstract class EVMChainClient { - late final client = ProxyWrapper().getHttpIOClient(); + final httpClient = Client(); Web3Client? _client; //! To be overridden by all child classes @@ -47,7 +47,7 @@ abstract class EVMChainClient { } _client = - Web3Client(isModifiedNodeUri ? rpcUri!.toString() : node.uri.toString(), client); + Web3Client(isModifiedNodeUri ? rpcUri!.toString() : node.uri.toString(), httpClient); return true; } catch (e) { @@ -76,7 +76,7 @@ abstract class EVMChainClient { Future getGasUnitPrice() async { try { final gasPrice = await _client!.getGasPrice(); - + return gasPrice.getInWei.toInt(); } catch (_) { return 0; @@ -101,7 +101,6 @@ abstract class EVMChainClient { String? contractAddress, EtherAmount? gasPrice, EtherAmount? maxFeePerGas, - Uint8List? data, }) async { try { if (contractAddress == null) { @@ -109,6 +108,7 @@ abstract class EVMChainClient { sender: senderAddress, to: toAddress, value: value, + // maxFeePerGas: maxFeePerGas, ); return estimatedGas.toInt(); @@ -124,7 +124,7 @@ abstract class EVMChainClient { final gasEstimate = await _client!.estimateGas( sender: senderAddress, to: EthereumAddress.fromHex(contractAddress), - data: data ?? transfer.encodeCall([ + data: transfer.encodeCall([ toAddress, value.getInWei, ]), @@ -137,21 +137,6 @@ abstract class EVMChainClient { } } - Uint8List getEncodedDataForApprovalTransaction({ - required EthereumAddress toAddress, - required EtherAmount value, - required EthereumAddress contractAddress, - }) { - final contract = DeployedContract(ethereumContractAbi, contractAddress); - - final approve = contract.function('approve'); - - return approve.encodeCall([ - toAddress, - value.getInWei, - ]); - } - Future signTransaction({ required Credentials privateKey, required String toAddress, @@ -164,7 +149,6 @@ abstract class EVMChainClient { required int exponent, String? contractAddress, String? data, - int? gasPrice, }) async { assert(currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly || @@ -180,7 +164,6 @@ abstract class EVMChainClient { data: data != null ? hexToBytes(data) : null, maxGas: estimatedGasUnits, maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), - gasPrice: gasPrice != null ? EtherAmount.fromInt(EtherUnit.wei, gasPrice) : null, ); Uint8List signedTransaction; @@ -215,52 +198,6 @@ abstract class EVMChainClient { ); } - Future signApprovalTransaction({ - required Credentials privateKey, - required String spender, - required BigInt amount, - required BigInt gasFee, - required int estimatedGasUnits, - required int maxFeePerGas, - required EVMChainTransactionPriority priority, - required int exponent, - required String contractAddress, - int? gasPrice, - }) async { - - final Transaction transaction = createTransaction( - from: privateKey.address, - to: EthereumAddress.fromHex(contractAddress), - maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), - amount: EtherAmount.zero(), - maxGas: estimatedGasUnits, - maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), - gasPrice: gasPrice != null ? EtherAmount.fromInt(EtherUnit.wei, gasPrice) : null, - ); - - final erc20 = ERC20( - client: _client!, - address: EthereumAddress.fromHex(contractAddress), - chainId: chainId, - ); - - final signedTransaction = await erc20.approve( - EthereumAddress.fromHex(spender), - amount, - credentials: privateKey, - transaction: transaction, - ); - - return PendingEVMChainTransaction( - signedTransaction: prepareSignedTransactionForSending(signedTransaction), - amount: amount.toString(), - fee: gasFee, - sendTransaction: () => sendTransaction(signedTransaction), - exponent: exponent, - isInfiniteApproval: amount.toRadixString(16) == 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - ); - } - Transaction createTransaction({ required EthereumAddress from, required EthereumAddress to, @@ -356,7 +293,7 @@ abstract class EVMChainClient { }, ); - final response = await client.get( + final response = await httpClient.get( uri, headers: { "Accept": "application/json", diff --git a/cw_evm/lib/evm_chain_exceptions.dart b/cw_evm/lib/evm_chain_exceptions.dart index 19bb047ef..c7509a17f 100644 --- a/cw_evm/lib/evm_chain_exceptions.dart +++ b/cw_evm/lib/evm_chain_exceptions.dart @@ -22,32 +22,3 @@ class EVMChainTransactionFeesException implements Exception { @override String toString() => exceptionMessage; } - -class DeuroGasFeeException implements Exception { - final String exceptionMessage; - final BigInt? requiredGasFee; - final BigInt? currentBalance; - - DeuroGasFeeException({ - this.requiredGasFee, - this.currentBalance, - }) : exceptionMessage = _buildMessage(requiredGasFee, currentBalance); - - static String _buildMessage(BigInt? requiredGasFee, BigInt? currentBalance) { - const baseMessage = 'Insufficient ETH for gas fees.'; - const addEthMessage = ' Please add ETH to your wallet to cover transaction fees.'; - - if (requiredGasFee != null) { - final requiredEth = (requiredGasFee / BigInt.from(10).pow(18)).toStringAsFixed(8); - final balanceInfo = currentBalance != null - ? ', Available: ${(currentBalance / BigInt.from(10).pow(18)).toStringAsFixed(8)} ETH' - : ''; - return '$baseMessage Required: ~$requiredEth ETH$balanceInfo.$addEthMessage'; - } - - return '$baseMessage$addEthMessage'; - } - - @override - String toString() => exceptionMessage; -} diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index a1285f0e4..d640f8c14 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; -import 'dart:typed_data'; import 'package:bip32/bip32.dart' as bip32; import 'package:bip39/bip39.dart' as bip39; @@ -137,7 +136,7 @@ abstract class EVMChainWalletBase //! Methods to be overridden by every child - void addInitialTokens([bool isMigration]); + void addInitialTokens(); // Future open({ // required String name, @@ -198,8 +197,8 @@ abstract class EVMChainWalletBase for (var token in erc20Currencies) { bool isPotentialScam = false; - bool isWhitelisted = getDefaultTokenContractAddresses - .any((element) => element.toLowerCase() == token.contractAddress.toLowerCase()); + bool isWhitelisted = + getDefaultTokenContractAddresses.any((element) => element == token.contractAddress); final tokenSymbol = token.title.toUpperCase(); @@ -214,16 +213,6 @@ abstract class EVMChainWalletBase token.iconPath = null; await token.save(); } - - // For fixing wrongly classified tokens - if (!isPotentialScam && token.isPotentialScam) { - token.isPotentialScam = false; - final iconPath = CryptoCurrency.all - .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) - .iconPath; - token.iconPath = iconPath; - await token.save(); - } } } @@ -266,72 +255,36 @@ abstract class EVMChainWalletBase required String? contractAddress, required String receivingAddressHex, required TransactionPriority priority, - Uint8List? data, }) async { try { if (priority is EVMChainTransactionPriority) { final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); int maxFeePerGas; - int adjustedGasPrice; - - bool isPolygon = _client.chainId == 137; - if (gasBaseFee != null) { // MaxFeePerGas with EIP1559; maxFeePerGas = gasBaseFee! + priorityFee; } else { // MaxFeePerGas with gasPrice - maxFeePerGas = gasPrice + priorityFee; - } - - adjustedGasPrice = maxFeePerGas; - - // Polygon has a minimum priority fee of 25 gwei - if (isPolygon) { - int minPriorityFee = 25; - int minPriorityFeeWei = - EtherAmount.fromInt(EtherUnit.gwei, minPriorityFee).getInWei.toInt(); - - // Calculate user selected priority-based additional fee on top of minimum - int additionalPriorityFee = 0; - switch (priority) { - case EVMChainTransactionPriority.slow: - // We use minimum priority fee only - additionalPriorityFee = 0; - break; - case EVMChainTransactionPriority.medium: - // We add 15 gwei on top of minimum - additionalPriorityFee = EtherAmount.fromInt(EtherUnit.gwei, 15).getInWei.toInt(); - break; - case EVMChainTransactionPriority.fast: - // We add 35 gwei on top of minimum - additionalPriorityFee = EtherAmount.fromInt(EtherUnit.gwei, 35).getInWei.toInt(); - break; - } - - int totalPriorityFee = minPriorityFeeWei + additionalPriorityFee; - adjustedGasPrice = gasPrice + totalPriorityFee; - maxFeePerGas = gasPrice + totalPriorityFee; + maxFeePerGas = gasPrice; } final estimatedGas = await _client.getEstimatedGasUnitsForTransaction( contractAddress: contractAddress, senderAddress: _evmChainPrivateKey.address, value: EtherAmount.fromBigInt(EtherUnit.wei, amount!), - gasPrice: EtherAmount.fromInt(EtherUnit.wei, adjustedGasPrice), + gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice), toAddress: EthereumAddress.fromHex(receivingAddressHex), maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), - data: data, ); - final totalGasFee = estimatedGas * adjustedGasPrice; + final totalGasFee = estimatedGas * maxFeePerGas; return GasParamsHandler( estimatedGasUnits: estimatedGas, estimatedGasFee: totalGasFee, maxFeePerGas: maxFeePerGas, - gasPrice: adjustedGasPrice, + gasPrice: gasPrice, ); } return GasParamsHandler.zero(); @@ -520,46 +473,11 @@ abstract class EVMChainWalletBase contractAddress: transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, data: hexOpReturnMemo, - gasPrice: maxFeePerGasForTransaction, ); return pendingEVMChainTransaction; } - Future createApprovalTransaction(BigInt amount, String spender, - CryptoCurrency token, EVMChainTransactionPriority priority) async { - final CryptoCurrency transactionCurrency = - balance.keys.firstWhere((element) => element.title == token.title); - assert(transactionCurrency is Erc20Token); - - final data = _client.getEncodedDataForApprovalTransaction( - contractAddress: EthereumAddress.fromHex((transactionCurrency as Erc20Token).contractAddress), - value: EtherAmount.fromBigInt(EtherUnit.wei, amount), - toAddress: EthereumAddress.fromHex(spender), - ); - - final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction( - amount: amount, - receivingAddressHex: spender, - priority: priority, - contractAddress: transactionCurrency.contractAddress, - data: data, - ); - - return _client.signApprovalTransaction( - privateKey: _evmChainPrivateKey, - spender: spender, - amount: amount, - priority: priority, - gasFee: BigInt.from(gasFeesModel.estimatedGasFee), - maxFeePerGas: gasFeesModel.maxFeePerGas, - estimatedGasUnits: gasFeesModel.estimatedGasUnits, - exponent: transactionCurrency.decimal, - contractAddress: transactionCurrency.contractAddress, - gasPrice: gasFeesModel.gasPrice, - ); - } - Future _updateTransactions() async { try { if (_isTransactionUpdating) { diff --git a/cw_evm/lib/pending_evm_chain_transaction.dart b/cw_evm/lib/pending_evm_chain_transaction.dart index 61b406470..6861b41f8 100644 --- a/cw_evm/lib/pending_evm_chain_transaction.dart +++ b/cw_evm/lib/pending_evm_chain_transaction.dart @@ -11,7 +11,6 @@ class PendingEVMChainTransaction with PendingTransaction { final BigInt fee; final String amount; final int exponent; - final bool isInfiniteApproval; PendingEVMChainTransaction({ required this.sendTransaction, @@ -19,12 +18,10 @@ class PendingEVMChainTransaction with PendingTransaction { required this.fee, required this.amount, required this.exponent, - this.isInfiniteApproval = false, }); @override String get amountFormatted { - if (isInfiniteApproval) return "∞"; final _amount = (BigInt.parse(amount) / BigInt.from(pow(10, exponent))).toString(); return _amount.substring(0, min(10, _amount.length)); } diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml index 80788ca06..326ff4dc9 100644 --- a/cw_evm/pubspec.yaml +++ b/cw_evm/pubspec.yaml @@ -30,7 +30,6 @@ dependencies: git: url: https://github.com/cake-tech/ledger-flutter-plus-plugins path: packages/ledger-ethereum - ref: f4761cd5171d4c1e2e42fd3298261650539fb2db dependency_overrides: web3dart: @@ -42,9 +41,9 @@ dependency_overrides: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 flutter_lints: ^2.0.0 flutter: diff --git a/cw_monero/lib/api/account_list.dart b/cw_monero/lib/api/account_list.dart index b753b4656..7f6a3f1aa 100644 --- a/cw_monero/lib/api/account_list.dart +++ b/cw_monero/lib/api/account_list.dart @@ -25,8 +25,8 @@ bool isUpdating = false; void refreshAccounts() { try { isUpdating = true; - subaddressAccount = currentWallet?.subaddressAccount(); - subaddressAccount?.refresh(); + subaddressAccount = currentWallet!.subaddressAccount(); + subaddressAccount!.refresh(); isUpdating = false; } catch (e) { isUpdating = false; diff --git a/cw_monero/lib/api/structs/pending_transaction.dart b/cw_monero/lib/api/structs/pending_transaction.dart index 22f974f4b..dc5fbddd0 100644 --- a/cw_monero/lib/api/structs/pending_transaction.dart +++ b/cw_monero/lib/api/structs/pending_transaction.dart @@ -5,11 +5,13 @@ class PendingTransactionDescription { required this.fee, required this.hash, required this.hex, + required this.txKey, required this.pointerAddress}); final int amount; final int fee; final String hash; final String hex; + final String txKey; final int pointerAddress; } \ No newline at end of file diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index fd6004140..4360149d2 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:ffi'; import 'dart:isolate'; @@ -195,12 +194,14 @@ Future createTransactionSync( final rFee = pendingTx.fee(); final rHash = pendingTx.txid(''); final rHex = pendingTx.hex(''); + final rTxKey = rHash; return PendingTransactionDescription( amount: rAmt, fee: rFee, hash: rHash, hex: rHex, + txKey: rTxKey, pointerAddress: pendingTx.ffiAddress(), ); } @@ -245,23 +246,23 @@ Future createTransactionMultDest( fee: tx.fee(), hash: tx.txid(''), hex: tx.hex(''), + txKey: tx.txid(''), pointerAddress: tx.ffiAddress(), ); } -Future commitTransactionFromPointerAddress({required int address, required bool useUR}) => +String? commitTransactionFromPointerAddress({required int address, required bool useUR}) => commitTransaction(tx: MoneroPendingTransaction(Pointer.fromAddress(address)), useUR: useUR); -Future commitTransaction({required Wallet2PendingTransaction tx, required bool useUR}) async { +String? commitTransaction({required Wallet2PendingTransaction tx, required bool useUR}) { final txCommit = useUR ? tx.commitUR(120) - : await Isolate.run(() { + : Isolate.run(() { monero.PendingTransaction_commit( Pointer.fromAddress(tx.ffiAddress()), filename: '', overwrite: false, ); - return null; }); String? error = (() { @@ -284,12 +285,11 @@ Future commitTransaction({required Wallet2PendingTransaction tx, requir if (error != null && error != "no tx keys found for this txid") { throw CreationTransactionException(message: error); } - unawaited(() async { - storeSync(force: true); - await Future.delayed(Duration(seconds: 5)); - storeSync(force: true); - }()); - return Future.value(txCommit); + if (useUR) { + return txCommit as String?; + } else { + return null; + } } class Transaction { diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index 148b271ff..8c5ab2d41 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -116,17 +116,12 @@ String getSeedLegacy(String? language) { } String getPassphrase() { - return currentWallet?.getCacheAttribute(key: "cakewallet.passphrase") ?? ""; + return currentWallet!.getCacheAttribute(key: "cakewallet.passphrase"); } Map>> addressCache = {}; String getAddress({int accountIndex = 0, int addressIndex = 0}) { - // this is a workaround for when we switch the wallet pointer, - // it should never reach UI but should be good enough to prevent gray screen - // or other errors because of forced null check. - if (currentWallet == null) return ""; - // printV("getaddress: ${accountIndex}/${addressIndex}: ${monero.Wallet_numSubaddresses(wptr!, accountIndex: accountIndex)}: ${monero.Wallet_address(wptr!, accountIndex: accountIndex, addressIndex: addressIndex)}"); // this could be a while loop, but I'm in favor of making it if to not cause freezes if (currentWallet!.numSubaddresses(accountIndex: accountIndex)-1 < addressIndex) { @@ -151,25 +146,7 @@ int getUnlockedBalance({int accountIndex = 0}) => int getCurrentHeight() => currentWallet?.blockChainHeight() ?? 0; - -int cachedNodeHeight = 0; -bool isHeightRefreshing = false; -int getNodeHeightSync() { - if (isHeightRefreshing == false) { - (() async { - try { - isHeightRefreshing = true; - final wptrAddress = currentWallet!.ffiAddress(); - cachedNodeHeight = await Isolate.run(() async { - return monero.Wallet_daemonBlockChainHeight(Pointer.fromAddress(wptrAddress)); - }); - } finally { - isHeightRefreshing = false; - } - })(); - } - return cachedNodeHeight; -} +int getNodeHeightSync() => currentWallet?.daemonBlockChainHeight() ?? 0; bool isConnectedSync() => currentWallet?.connected() != 0; @@ -225,6 +202,7 @@ Future setupNodeSync( } void startRefreshSync() { + currentWallet!.refreshAsync(); currentWallet!.startRefresh(); } @@ -250,7 +228,7 @@ void storeSync({bool force = false}) async { return monero.Wallet_synchronized(Pointer.fromAddress(addr)); }); if (lastStorePointer == addr && - lastStoreHeight + 75000 > currentWallet!.blockChainHeight() && + lastStoreHeight + 5000 > currentWallet!.blockChainHeight() && !synchronized && !force) { return; @@ -277,13 +255,13 @@ void closeCurrentWallet() { currentWallet!.stop(); } -String getSecretViewKey() => currentWallet?.secretViewKey() ?? ""; +String getSecretViewKey() => currentWallet!.secretViewKey(); -String getPublicViewKey() => currentWallet?.publicViewKey() ?? ""; +String getPublicViewKey() => currentWallet!.publicViewKey(); -String getSecretSpendKey() => currentWallet?.secretSpendKey() ?? ""; +String getSecretSpendKey() => currentWallet!.secretSpendKey(); -String getPublicSpendKey() => currentWallet?.publicSpendKey() ?? ""; +String getPublicSpendKey() => currentWallet!.publicSpendKey(); class SyncListener { SyncListener(this.onNewBlock, this.onNewTransaction) diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index 97f1de275..9b369c155 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -388,7 +388,9 @@ Future loadWallet( if (gLedger == null) { throw Exception("Tried to open a ledger wallet with no ledger connected"); } - enableLedgerExchange(gLedger!); + final dummyWPtr = (currentWallet ?? + wmPtr.openWallet(path: '', password: '')); + enableLedgerExchange(dummyWPtr, gLedger!); } final addr = wmPtr.ffiAddress(); diff --git a/cw_monero/lib/ledger.dart b/cw_monero/lib/ledger.dart index 6e32d4d68..d931b58d0 100644 --- a/cw_monero/lib/ledger.dart +++ b/cw_monero/lib/ledger.dart @@ -2,50 +2,75 @@ import 'dart:async'; import 'dart:ffi'; import 'dart:typed_data'; +import 'package:collection/collection.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:ffi/ffi.dart'; -import 'package:flutter/foundation.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus_dart.dart'; -import 'package:monero/src/monero.dart' as api; +import 'package:monero/src/wallet2.dart'; LedgerConnection? gLedger; -String? latestLedgerCommand; -typedef LedgerCallback = Void Function(Pointer, UnsignedInt); -NativeCallable? callable; +Timer? _ledgerExchangeTimer; +Timer? _ledgerKeepAlive; -void enableLedgerExchange(LedgerConnection connection) { - callable?.close(); +void enableLedgerExchange(Wallet2Wallet wallet, LedgerConnection connection) { + _ledgerExchangeTimer?.cancel(); + _ledgerExchangeTimer = Timer.periodic(Duration(milliseconds: 1), (_) async { + final ledgerRequestLength = wallet.getSendToDeviceLength(); + final ledgerRequest = wallet.getSendToDevice() + .cast() + .asTypedList(ledgerRequestLength); + if (ledgerRequestLength > 0) { + _ledgerKeepAlive?.cancel(); - void callback(Pointer request, int requestLength) async { - final ledgerRequest = request.cast().asTypedList(requestLength); + final Pointer emptyPointer = malloc(0); + wallet.setDeviceSendData( + emptyPointer.cast(), 0); + malloc.free(emptyPointer); - _logLedgerCommand(ledgerRequest, false); - final response = await exchange(connection, ledgerRequest); - _logLedgerCommand(response, true); + _logLedgerCommand(ledgerRequest, false); + final response = await exchange(connection, ledgerRequest); + _logLedgerCommand(response, true); - final Pointer result = malloc(response.length); - for (var i = 0; i < response.length; i++) { - result.asTypedList(response.length)[i] = response[i]; + if (ListEquality().equals(response, [0x55, 0x15])) { + await connection.disconnect(); + // // TODO: Show POPUP pls unlock your device + // await Future.delayed(Duration(seconds: 15)); + // response = await exchange(connection, ledgerRequest); + } + + final Pointer result = malloc(response.length); + for (var i = 0; i < response.length; i++) { + result.asTypedList(response.length)[i] = response[i]; + } + + wallet.setDeviceReceivedData( + result.cast(), response.length); + malloc.free(result); + keepAlive(connection); } + }); +} - latestLedgerCommand = _ledgerMoneroCommands[ledgerRequest[1]]; - - api.MoneroWallet.setDeviceReceivedData( - result.cast(), response.length); - api.MoneroFree().free(result.cast()); +void keepAlive(LedgerConnection connection) { + if (connection.connectionType == ConnectionType.ble) { + _ledgerKeepAlive = Timer.periodic(Duration(seconds: 10), (_) async { + UniversalBle.setNotifiable( + connection.device.id, + connection.device.deviceInfo.serviceId, + connection.device.deviceInfo.notifyCharacteristicKey, + BleInputProperty.notification, + ).onError((_, __) async {}); + }); } - - callable = NativeCallable.listener(callback); - api.MoneroWallet.setLedgerCallback(callable!.nativeFunction); } void disableLedgerExchange() { - callable?.close(); + _ledgerExchangeTimer?.cancel(); + _ledgerKeepAlive?.cancel(); gLedger?.disconnect(); gLedger = null; - latestLedgerCommand = null; } Future exchange(LedgerConnection connection, Uint8List data) async => @@ -110,6 +135,8 @@ void _logLedgerCommand(Uint8List command, [bool isResponse = true]) { String toHexString(Uint8List data) => data.map((e) => e.toRadixString(16).padLeft(2, '0')).join(); + + if (isResponse) { printV("< ${toHexString(command)}"); } else { diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 9a8cb70b4..7a4d943fe 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -17,7 +17,6 @@ import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; @@ -35,12 +34,12 @@ import 'package:cw_monero/monero_transaction_history.dart'; import 'package:cw_monero/monero_transaction_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:cw_monero/monero_wallet_addresses.dart'; -import 'package:cw_monero/monero_wallet_service.dart'; import 'package:cw_monero/pending_monero_transaction.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; import 'package:mobx/mobx.dart'; +import 'package:monero/src/monero.dart' as m; import 'package:monero/monero.dart' as monero; part 'monero_wallet.g.dart'; @@ -194,7 +193,19 @@ abstract class MoneroWalletBase extends WalletBase connectToNode({required Node node}) async { - String socksProxy = node.socksProxyAddress ?? ''; - printV("bootstrapped: ${CakeTor.instance.bootstrapped}"); - printV(" enabled: ${CakeTor.instance.enabled}"); - printV(" port: ${CakeTor.instance.port}"); - printV(" started: ${CakeTor.instance.started}"); - if (CakeTor.instance.enabled) { - socksProxy = "127.0.0.1:${CakeTor.instance.port}"; - } try { syncStatus = ConnectingSyncStatus(); await monero_wallet.setupNodeSync( @@ -225,7 +228,7 @@ abstract class MoneroWalletBase extends WalletBase closeWalletAwaitIfShould(int wmaddr, int waddr) async { - if (Platform.isWindows) { - await Isolate.run(() { - monero.WalletManager_closeWallet( - Pointer.fromAddress(wmaddr), Pointer.fromAddress(waddr), true); - monero.WalletManager_errorString(Pointer.fromAddress(wmaddr)); - }); - } else { - unawaited(Isolate.run(() { - monero.WalletManager_closeWallet( - Pointer.fromAddress(wmaddr), Pointer.fromAddress(waddr), true); - monero.WalletManager_errorString(Pointer.fromAddress(wmaddr)); - })); - } -} \ No newline at end of file diff --git a/cw_monero/lib/pending_monero_transaction.dart b/cw_monero/lib/pending_monero_transaction.dart index 9909a3021..1c01a60dc 100644 --- a/cw_monero/lib/pending_monero_transaction.dart +++ b/cw_monero/lib/pending_monero_transaction.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:cw_monero/api/account_list.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; import 'package:cw_monero/api/transaction_history.dart' @@ -9,7 +7,6 @@ import 'package:cw_core/amount_converter.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_monero/api/wallet.dart'; -import 'package:cw_monero/monero_wallet.dart'; class DoubleSpendException implements Exception { DoubleSpendException(); @@ -20,10 +17,9 @@ class DoubleSpendException implements Exception { } class PendingMoneroTransaction with PendingTransaction { - PendingMoneroTransaction(this.pendingTransactionDescription, this.wallet); + PendingMoneroTransaction(this.pendingTransactionDescription); final PendingTransactionDescription pendingTransactionDescription; - final MoneroWalletBase wallet; @override String get id => pendingTransactionDescription.hash; @@ -31,6 +27,8 @@ class PendingMoneroTransaction with PendingTransaction { @override String get hex => pendingTransactionDescription.hex; + String get txKey => pendingTransactionDescription.txKey; + @override String get amountFormatted => AmountConverter.amountIntToString( CryptoCurrency.xmr, pendingTransactionDescription.amount); @@ -44,7 +42,7 @@ class PendingMoneroTransaction with PendingTransaction { @override Future commit() async { try { - await monero_transaction_history.commitTransactionFromPointerAddress( + monero_transaction_history.commitTransactionFromPointerAddress( address: pendingTransactionDescription.pointerAddress, useUR: false); } catch (e) { @@ -57,23 +55,14 @@ class PendingMoneroTransaction with PendingTransaction { rethrow; } storeSync(force: true); - unawaited(() async { - await Future.delayed(const Duration(milliseconds: 250)); - await wallet.fetchTransactions(); - }()); } @override Future commitUR() async { try { - final ret = await monero_transaction_history.commitTransactionFromPointerAddress( + final ret = monero_transaction_history.commitTransactionFromPointerAddress( address: pendingTransactionDescription.pointerAddress, useUR: true); - storeSync(force: true); - unawaited(() async { - await Future.delayed(const Duration(milliseconds: 250)); - await wallet.fetchTransactions(); - }()); return ret; } catch (e) { final message = e.toString(); diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 2de22ed11..0140c39aa 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -66,11 +66,11 @@ packages: dependency: transitive description: path: "." - ref: cake-update-v4 - resolved-ref: "437dadd0bd9bf73ec6a551299577799341f6486a" + ref: cake-update-v2 + resolved-ref: "59fdf29d72068e0522a96a8953ed7272833a9f57" url: "https://github.com/cake-tech/blockchain_utils" source: git - version: "4.3.0" + version: "3.3.0" bluez: dependency: transitive description: @@ -131,18 +131,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.2.10" built_collection: dependency: transitive description: @@ -573,8 +573,8 @@ packages: dependency: "direct main" description: path: "impls/monero.dart" - ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 - resolved-ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 + ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 + resolved-ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 url: "https://github.com/mrcyjanek/monero_c" source: git version: "0.0.0" @@ -599,10 +599,10 @@ packages: description: path: "." ref: cake-update-v2 - resolved-ref: "084fb7bf13ec42d74f26ac08c883ce07c10fca7e" + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2" url: "https://github.com/cake-tech/on_chain.git" source: git - version: "6.2.0" + version: "3.7.0" package_config: dependency: transitive description: @@ -779,21 +779,11 @@ packages: socks5_proxy: dependency: transitive description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: transitive - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: @@ -870,19 +860,10 @@ packages: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" - tor_binary: - dependency: transitive - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" + version: "1.0.2" tuple: dependency: transitive description: @@ -997,4 +978,4 @@ packages: version: "3.1.3" sdks: dart: ">=3.6.0 <4.0.0" - flutter: ">=3.24.0" + flutter: ">=3.27.4" diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index a11e85b6c..90d0b85ab 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -2,10 +2,11 @@ name: cw_monero description: A new flutter plugin project. version: 0.0.1 publish_to: none +author: Cake Wallet homepage: https://cakewallet.com environment: - sdk: ^3.5.0 + sdk: ">=2.19.0 <3.0.0" flutter: ">=1.20.0" dependencies: @@ -26,7 +27,7 @@ dependencies: monero: git: url: https://github.com/mrcyjanek/monero_c - ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 + ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 path: impls/monero.dart mutex: ^3.1.0 ledger_flutter_plus: ^1.4.1 @@ -34,8 +35,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 - build_resolvers: ^2.4.4 + build_runner: ^2.4.7 + build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 mockito: ^5.4.5 hive_generator: ^2.0.1 diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index c852a8c0d..b63c634ee 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -3,11 +3,11 @@ import 'dart:convert'; import 'package:cw_core/nano_account_info_response.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_nano/nano_block_info_response.dart'; import 'package:cw_core/n2_node.dart'; import 'package:cw_nano/nano_balance.dart'; import 'package:cw_nano/nano_transaction_model.dart'; +import 'package:http/http.dart' as http; import 'package:cw_core/node.dart'; import 'package:nanoutil/nanoutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -66,8 +66,8 @@ class NanoClient { } Future getBalance(String address) async { - final response = await ProxyWrapper().post( - clearnetUri: _node!.uri, + final response = await http.post( + _node!.uri, headers: getHeaders(_node!.uri.host), body: jsonEncode( { @@ -76,8 +76,7 @@ class NanoClient { }, ), ); - - final data = jsonDecode(response.body) as Map; + final data = await jsonDecode(response.body); if (response.statusCode != 200 || data["error"] != null || data["balance"] == null || @@ -94,8 +93,8 @@ class NanoClient { Future getAccountInfo(String address) async { try { - final response = await ProxyWrapper().post( - clearnetUri: _node!.uri, + final response = await http.post( + _node!.uri, headers: getHeaders(_node!.uri.host), body: jsonEncode( { @@ -105,9 +104,8 @@ class NanoClient { }, ), ); - - final data = jsonDecode(response.body) as Map; - return AccountInfoResponse.fromJson(data); + final data = await jsonDecode(response.body); + return AccountInfoResponse.fromJson(data as Map); } catch (e) { printV("error while getting account info $e"); return null; @@ -116,8 +114,8 @@ class NanoClient { Future getBlockContents(String block) async { try { - final response = await ProxyWrapper().post( - clearnetUri: _node!.uri, + final response = await http.post( + _node!.uri, headers: getHeaders(_node!.uri.host), body: jsonEncode( { @@ -127,8 +125,7 @@ class NanoClient { }, ), ); - - final data = jsonDecode(response.body) as Map; + final data = await jsonDecode(response.body); return BlockContentsResponse.fromJson(data["contents"] as Map); } catch (e) { printV("error while getting block info $e"); @@ -184,8 +181,8 @@ class NanoClient { } Future requestWork(String hash) async { - final response = await ProxyWrapper().post( - clearnetUri: _powNode!.uri, + final response = await http.post( + _powNode!.uri, headers: getHeaders(_powNode!.uri.host), body: json.encode( { @@ -194,9 +191,8 @@ class NanoClient { }, ), ); - if (response.statusCode == 200) { - final decoded = jsonDecode(response.body) as Map; + final Map decoded = json.decode(response.body) as Map; if (decoded.containsKey("error")) { throw Exception("Received error ${decoded["error"]}"); } @@ -228,13 +224,13 @@ class NanoClient { "block": block, }); - final processResponse = await ProxyWrapper().post( - clearnetUri: _node!.uri, + final processResponse = await http.post( + _node!.uri, headers: getHeaders(_node!.uri.host), body: processBody, ); - final Map decoded = jsonDecode(processResponse.body) as Map; + final Map decoded = json.decode(processResponse.body) as Map; if (decoded.containsKey("error")) { throw Exception("Received error ${decoded["error"]}"); } @@ -427,11 +423,12 @@ class NanoClient { "subtype": "receive", "block": receiveBlock, }); - final processResponse = await ProxyWrapper().post( - clearnetUri: _node!.uri, + final processResponse = await http.post( + _node!.uri, headers: getHeaders(_node!.uri.host), body: processBody, ); + final Map decoded = json.decode(processResponse.body) as Map; if (decoded.containsKey("error")) { throw Exception("Received error ${decoded["error"]}"); @@ -443,17 +440,16 @@ class NanoClient { required String destinationAddress, required String privateKey, }) async { - final receivableResponse = await ProxyWrapper().post( - clearnetUri: _node!.uri, - headers: getHeaders(_node!.uri.host), - body: jsonEncode({ - "action": "receivable", - "account": destinationAddress, - "count": "-1", - "source": true, - }), - ); - final receivableData = jsonDecode(receivableResponse.body) as Map; + final receivableResponse = await http.post(_node!.uri, + headers: getHeaders(_node!.uri.host), + body: jsonEncode({ + "action": "receivable", + "account": destinationAddress, + "count": "-1", + "source": true, + })); + + final receivableData = await jsonDecode(receivableResponse.body); if (receivableData["blocks"] == "" || receivableData["blocks"] == null) { return 0; } @@ -496,18 +492,15 @@ class NanoClient { Future> fetchTransactions(String address) async { try { - final response = await ProxyWrapper().post( - clearnetUri: _node!.uri, - headers: getHeaders(_node!.uri.host), - body: jsonEncode({ - "action": "account_history", - "account": address, - "count": "100", - // "raw": true, - }), - ); - - final data = jsonDecode(response.body) as Map; + final response = await http.post(_node!.uri, + headers: getHeaders(_node!.uri.host), + body: jsonEncode({ + "action": "account_history", + "account": address, + "count": "100", + // "raw": true, + })); + final data = await jsonDecode(response.body); final transactions = data["history"] is List ? data["history"] as List : []; // Map the transactions list to NanoTransactionModel using the factory @@ -523,14 +516,13 @@ class NanoClient { Future> getN2Reps() async { final uri = Uri.parse(N2_REPS_ENDPOINT); - final response = await ProxyWrapper().post( - clearnetUri: uri, + final response = await http.post( + uri, headers: getHeaders(uri.host), body: jsonEncode({"action": "reps"}), ); try { - - final List nodes = (jsonDecode(response.body) as List) + final List nodes = (json.decode(response.body) as List) .map((dynamic e) => N2Node.fromJson(e as Map)) .toList(); return nodes; @@ -541,8 +533,8 @@ class NanoClient { Future getRepScore(String rep) async { final uri = Uri.parse(N2_REPS_ENDPOINT); - final response = await ProxyWrapper().post( - clearnetUri: uri, + final response = await http.post( + uri, headers: getHeaders(uri.host), body: jsonEncode({ "action": "rep_info", @@ -550,8 +542,7 @@ class NanoClient { }), ); try { - - final N2Node node = N2Node.fromJson(jsonDecode(response.body) as Map); + final N2Node node = N2Node.fromJson(json.decode(response.body) as Map); return node.score ?? 100; } catch (error) { return 100; diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index aa85d6dde..1eb90852d 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -5,39 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" url: "https://pub.dev" source: hosted - version: "76.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.3" + version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" url: "https://pub.dev" source: hosted - version: "6.11.0" + version: "4.7.0" args: dependency: transitive description: name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.6.0" asn1lib: dependency: transitive description: name: asn1lib - sha256: "1c296cd268f486cabcc3930e9b93a8133169305f18d722916e675959a88f6d2c" + sha256: "4bae5ae63e6d6dd17c4aac8086f3dec26c0236f6a0f03416c6c19d830c367cf5" url: "https://pub.dev" source: hosted - version: "1.5.9" + version: "1.5.8" async: dependency: transitive description: @@ -91,50 +86,50 @@ packages: dependency: transitive description: name: build - sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.1" build_config: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.2" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: - dependency: transitive + dependency: "direct overridden" description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: "0671ad4162ed510b70d0eb4ad6354c249f8429cab4ae7a4cec86bbc2886eb76e" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.2.7+1" built_collection: dependency: transitive description: @@ -147,10 +142,10 @@ packages: dependency: transitive description: name: built_value - sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27" + sha256: "8b158ab94ec6913e480dc3f752418348b5ae099eb75868b5f4775f0572999c61" url: "https://pub.dev" source: hosted - version: "8.10.1" + version: "8.9.4" cake_backup: dependency: transitive description: @@ -243,10 +238,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" url: "https://pub.dev" source: hosted - version: "2.3.8" + version: "2.2.4" decimal: dependency: "direct main" description: @@ -378,18 +373,18 @@ packages: dependency: "direct dev" description: name: hive_generator - sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "1.1.3" http: dependency: "direct main" description: name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" http_multi_server: dependency: transitive description: @@ -402,10 +397,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.1.2" + version: "4.0.2" intl: dependency: transitive description: @@ -478,14 +473,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" - url: "https://pub.dev" - source: hosted - version: "0.1.3-main.0" matcher: dependency: transitive description: @@ -530,10 +517,10 @@ packages: dependency: "direct dev" description: name: mobx_codegen - sha256: e0abbbc651a69550440f6b65c99ec222a1e2a4afd7baec8ba0f3088c7ca582a8 + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.7.1" + version: "2.3.0" nanodart: dependency: transitive description: @@ -564,7 +551,7 @@ packages: description: path: "." ref: cake-update-v2 - resolved-ref: "01cbbacbb05d2113aafa8b7c4a2bb766f749d8d8" + resolved-ref: "93440dc5126369b873ca1fccc13c3c1240b1c5c2" url: "https://github.com/cake-tech/on_chain.git" source: git version: "3.7.0" @@ -572,10 +559,10 @@ packages: dependency: transitive description: name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.1" path: dependency: transitive description: @@ -596,10 +583,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.2.15" path_provider_foundation: dependency: transitive description: @@ -676,26 +663,26 @@ packages: dependency: transitive description: name: provider - sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.1.2" pub_semver: dependency: transitive description: name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.5" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.4.0" rational: dependency: transitive description: @@ -708,18 +695,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + sha256: a768fc8ede5f0c8e6150476e14f38e2417c0864ca36bb4582be8e21925a03c22 url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.4.6" shared_preferences_foundation: dependency: transitive description: @@ -764,18 +751,18 @@ packages: dependency: transitive description: name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "2.0.1" sky_engine: dependency: transitive description: flutter @@ -784,37 +771,27 @@ packages: socks5_proxy: dependency: transitive description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: transitive - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" url: "https://pub.dev" source: hosted - version: "1.3.5" + version: "1.3.3" source_span: dependency: transitive description: @@ -875,19 +852,10 @@ packages: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" - tor_binary: - dependency: transitive - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" + version: "1.0.2" tuple: dependency: transitive description: @@ -948,18 +916,18 @@ packages: dependency: transitive description: name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" xdg_directories: dependency: transitive description: @@ -977,5 +945,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.27.4" diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index a85a4aee5..3ddd9769e 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -31,12 +31,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 dependency_overrides: watcher: ^1.1.0 + build_runner_core: 7.2.7+1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_polygon/lib/default_polygon_erc20_tokens.dart b/cw_polygon/lib/default_polygon_erc20_tokens.dart index 208a63345..deff285c0 100644 --- a/cw_polygon/lib/default_polygon_erc20_tokens.dart +++ b/cw_polygon/lib/default_polygon_erc20_tokens.dart @@ -31,13 +31,6 @@ class DefaultPolygonErc20Tokens { decimal: 6, enabled: true, ), - Erc20Token( - name: "Decentralized Euro", - symbol: "DEURO", - contractAddress: "0xC2ff25dD99e467d2589b2c26EDd270F220F14E47", - decimal: 18, - enabled: true, - ), Erc20Token( name: "Avalanche Token", symbol: "AVAX", @@ -84,6 +77,6 @@ class DefaultPolygonErc20Tokens { .iconPath; } catch (_) {} - return Erc20Token.copyWith(token, iconPath, 'POL'); + return Erc20Token.copyWith(token, iconPath, 'POLY'); }).toList(); } diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 62dcec50e..cb8331977 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -18,20 +18,13 @@ class PolygonClient extends EVMChainClient { EtherAmount? gasPrice, EtherAmount? maxFeePerGas, }) { - EtherAmount? finalGasPrice = gasPrice; - - if (gasPrice == null && maxFeePerGas != null) { - // If we have EIP-1559 parameters but no legacy gasPrice, then use maxFeePerGas as gasPrice - finalGasPrice = maxFeePerGas; - } - return Transaction( from: from, to: to, value: amount, - data: data, + // data: data, maxGas: maxGas, - gasPrice: finalGasPrice, + // gasPrice: gasPrice, // maxFeePerGas: maxFeePerGas, // maxPriorityFeePerGas: maxPriorityFeePerGas, ); @@ -47,13 +40,12 @@ class PolygonClient extends EVMChainClient { Future> fetchTransactions(String address, {String? contractAddress}) async { try { - final response = await client.get(Uri.https("api.etherscan.io", "/v2/api", { - "chainid": "$chainId", + final response = await httpClient.get(Uri.https("api.polygonscan.com", "/api", { "module": "account", "action": contractAddress != null ? "tokentx" : "txlist", if (contractAddress != null) "contractaddress": contractAddress, "address": address, - "apikey": secrets.etherScanApiKey, + "apikey": secrets.polygonScanApiKey, })); final jsonResponse = json.decode(response.body) as Map; @@ -75,12 +67,11 @@ class PolygonClient extends EVMChainClient { @override Future> fetchInternalTransactions(String address) async { try { - final response = await client.get(Uri.https("api.etherscan.io", "/v2/api", { - "chainid": "$chainId", + final response = await httpClient.get(Uri.https("api.polygonscan.io", "/api", { "module": "account", "action": "txlistinternal", "address": address, - "apikey": secrets.etherScanApiKey, + "apikey": secrets.polygonScanApiKey, })); final jsonResponse = json.decode(response.body) as Map; diff --git a/cw_polygon/lib/polygon_wallet.dart b/cw_polygon/lib/polygon_wallet.dart index 991552068..b2bf064b1 100644 --- a/cw_polygon/lib/polygon_wallet.dart +++ b/cw_polygon/lib/polygon_wallet.dart @@ -41,19 +41,11 @@ class PolygonWallet extends EVMChainWallet { } @override - void addInitialTokens([bool isMigration = false]) { + void addInitialTokens() { final initialErc20Tokens = DefaultPolygonErc20Tokens().initialPolygonErc20Tokens; - for (final token in initialErc20Tokens) { - if (evmChainErc20TokensBox.containsKey(token.contractAddress)) { - final existingToken = evmChainErc20TokensBox.get(token.contractAddress); - if (existingToken?.tag != token.tag) { - evmChainErc20TokensBox.put(token.contractAddress, token); - } - } else { - if (isMigration) token.enabled = false; - evmChainErc20TokensBox.put(token.contractAddress, token); - } + for (var token in initialErc20Tokens) { + evmChainErc20TokensBox.put(token.contractAddress, token); } } diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 05af311e7..994912e8d 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -55,7 +55,6 @@ class PolygonWalletService extends EVMChainWalletService { ); await wallet.init(); - wallet.addInitialTokens(true); await wallet.save(); saveBackup(name); return wallet; diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index bcbd80443..8421562b4 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -34,7 +34,7 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.4.15 + build_runner: ^2.4.7 # For information on the generic Dart part of this file, see the diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart index d57da5af0..05b0cec82 100644 --- a/cw_solana/lib/solana_client.dart +++ b/cw_solana/lib/solana_client.dart @@ -2,10 +2,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math' as math; -import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/node.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/solana_rpc_http_service.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_solana/pending_solana_transaction.dart'; @@ -13,17 +11,14 @@ import 'package:cw_solana/solana_balance.dart'; import 'package:cw_solana/solana_exceptions.dart'; import 'package:cw_solana/solana_transaction_model.dart'; import 'package:cw_solana/spl_token.dart'; +import 'package:http/http.dart' as http; import 'package:on_chain/solana/solana.dart'; -import 'package:on_chain/solana/src/instructions/associated_token_account/constant.dart'; import 'package:on_chain/solana/src/models/pda/pda.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; -import 'package:on_chain/solana/src/rpc/models/models/confirmed_transaction_meta.dart'; import '.secrets.g.dart' as secrets; class SolanaWalletClient { - // Minimum amount in SOL to consider a transaction valid (to filter spam) - static const double minValidAmount = 0.00000003; - final httpClient = ProxyWrapper().getHttpClient(); + final httpClient = http.Client(); SolanaRPC? _provider; bool connect(Node node) { @@ -87,8 +82,7 @@ class SolanaWalletClient { } } - Future getSplTokenBalance( - String mintAddress, String walletAddress) async { + Future getSplTokenBalance(String mintAddress, String walletAddress) async { // Fetch the token accounts (a token can have multiple accounts for various uses) final tokenAccounts = await getSPLTokenAccounts(mintAddress, walletAddress); @@ -124,16 +118,14 @@ class SolanaWalletClient { ), ); - final fee = - (feeForMessage?.toDouble() ?? 0.0) / SolanaUtils.lamportsPerSol; + final fee = (feeForMessage?.toDouble() ?? 0.0) / SolanaUtils.lamportsPerSol; return fee; } catch (_) { return 0.0; } } - Future getEstimatedFee( - SolanaPublicKey publicKey, Commitment commitment) async { + Future getEstimatedFee(SolanaPublicKey publicKey, Commitment commitment) async { final message = await _getMessageForNativeTransaction( publicKey: publicKey, destinationAddress: publicKey.toAddress().address, @@ -163,88 +155,170 @@ class SolanaWalletClient { if (meta == null || transaction == null) return null; final int fee = meta.fee; - final feeInSol = fee / SolanaUtils.lamportsPerSol; final message = transaction.message; final instructions = message.compiledInstructions; + String sender = ""; + String receiver = ""; + String signature = (txResponse.transaction?.signatures.isEmpty ?? true) ? "" : Base58Encoder.encode(txResponse.transaction!.signatures.first); - for (final instruction in instructions) { final programId = message.accountKeys[instruction.programIdIndex]; - if (programId == SystemProgramConst.programId || - programId == ComputeBudgetConst.programId) { + if (programId == SystemProgramConst.programId) { // For native solana transactions - if (instruction.accounts.length < 2) continue; - // Get the fee payer index based on transaction type - // For legacy transfers, the first account is usually the fee payer - // For versioned, the first account in instruction is usually the fee payer - final feePayerIndex = - txResponse.version == TransactionType.legacy ? 0 : instruction.accounts[0]; + if (txResponse.version == TransactionType.legacy) { + // For legacy transfers, the fee payer (index 0) is the sender. + sender = message.accountKeys[0].address; - final transactionModel = await _parseNativeTransaction( - message: message, - meta: meta, - fee: fee, - feeInSol: feeInSol, - feePayerIndex: feePayerIndex, - walletAddress: walletAddress, - signature: signature, - blockTime: blockTime, - ); + final senderPreBalance = meta.preBalances[0]; + final senderPostBalance = meta.postBalances[0]; + final feeForTx = fee / SolanaUtils.lamportsPerSol; - if (transactionModel != null) { - return transactionModel; + // The loss on the sender's account would include both the transfer amount and the fee. + // So we would subtract the fee to calculate the actual amount that was transferred (in lamports). + final transferLamports = (senderPreBalance - senderPostBalance) - BigInt.from(fee); + + // Next, we attempt to find the receiver by comparing the balance changes. + // (The index 0 is for the sender so we skip it.) + bool foundReceiver = false; + for (int i = 1; i < meta.preBalances.length; i++) { + // The increase in balance on the receiver account should correspond to the transfer amount we calculated earlieer. + final pre = meta.preBalances[i]; + final post = meta.postBalances[i]; + if ((post - pre) == transferLamports) { + receiver = message.accountKeys[i].address; + foundReceiver = true; + break; + } + } + + if (!foundReceiver) { + // Optionally (and rarely), if no account shows the exact expected change, + // we set the receiver address to unknown. + receiver = "unknown"; + } + + final amount = transferLamports / BigInt.from(1e9); + + return SolanaTransactionModel( + isOutgoingTx: sender == walletAddress, + from: sender, + to: receiver, + id: signature, + amount: amount.abs(), + programId: SystemProgramConst.programId.address, + tokenSymbol: 'SOL', + blockTimeInInt: blockTime?.toInt() ?? 0, + fee: feeForTx, + ); + } else { + if (instruction.accounts.length < 2) continue; + final senderIndex = instruction.accounts[0]; + final receiverIndex = instruction.accounts[1]; + + sender = message.accountKeys[senderIndex].address; + receiver = message.accountKeys[receiverIndex].address; + + final feeForTx = fee / SolanaUtils.lamportsPerSol; + + final preBalances = meta.preBalances; + final postBalances = meta.postBalances; + + final amountInString = + (((preBalances[senderIndex] - postBalances[senderIndex]) / BigInt.from(1e9)) + .toDouble() - + feeForTx) + .toStringAsFixed(6); + + final amount = double.parse(amountInString); + + return SolanaTransactionModel( + isOutgoingTx: sender == walletAddress, + from: sender, + to: receiver, + id: signature, + amount: amount.abs(), + programId: SystemProgramConst.programId.address, + tokenSymbol: 'SOL', + blockTimeInInt: blockTime?.toInt() ?? 0, + fee: feeForTx, + ); } } else if (programId == SPLTokenProgramConst.tokenProgramId) { // For SPL Token transactions if (instruction.accounts.length < 2) continue; - final transactionModel = await _parseSPLTokenTransaction( - message: message, - meta: meta, - fee: fee, - feeInSol: feeInSol, - instruction: instruction, - walletAddress: walletAddress, - signature: signature, - blockTime: blockTime, - splTokenSymbol: splTokenSymbol, - ); + final preBalances = meta.preTokenBalances; + final postBalances = meta.postTokenBalances; - if (transactionModel != null) { - return transactionModel; - } - } else if (programId == AssociatedTokenAccountProgramConst.associatedTokenProgramId) { - // For ATA program, we need to check if this is a create account transaction - // or if it's part of a normal token transfer + double amount = 0.0; + bool isOutgoing = false; + String? mintAddress; - // We skip this transaction if this is the only instruction (this means that it's a create account transaction) - if (instructions.length == 1) { - return null; - } + double userPreAmount = 0.0; + if (preBalances != null && preBalances.isNotEmpty) { + for (final preBal in preBalances) { + if (preBal.owner?.address == walletAddress) { + userPreAmount = preBal.uiTokenAmount.uiAmount ?? 0.0; - // We look for a token transfer instruction in the same transaction - bool hasTokenTransfer = false; - for (final otherInstruction in instructions) { - final otherProgramId = message.accountKeys[otherInstruction.programIdIndex]; - if (otherProgramId == SPLTokenProgramConst.tokenProgramId) { - hasTokenTransfer = true; - break; + mintAddress = preBal.mint.address; + break; + } } } - // If there's no token transfer instruction, it means this is just an ATA creation transaction - if (!hasTokenTransfer) { - return null; + double userPostAmount = 0.0; + if (postBalances != null && postBalances.isNotEmpty) { + for (final postBal in postBalances) { + if (postBal.owner?.address == walletAddress) { + userPostAmount = postBal.uiTokenAmount.uiAmount ?? 0.0; + + mintAddress ??= postBal.mint.address; + break; + } + } } - continue; + final diff = userPreAmount - userPostAmount; + final rawAmount = diff.abs(); + + final amountInString = rawAmount.toStringAsFixed(6); + amount = double.parse(amountInString); + + isOutgoing = diff > 0; + + if (mintAddress == null && instruction.accounts.length >= 4) { + final mintIndex = instruction.accounts[3]; + mintAddress = message.accountKeys[mintIndex].address; + } + + final sender = message.accountKeys[instruction.accounts[0]].address; + final receiver = message.accountKeys[instruction.accounts[1]].address; + + String? tokenSymbol = splTokenSymbol; + + if (tokenSymbol == null && mintAddress != null) { + final token = await getTokenInfo(mintAddress); + tokenSymbol = token?.symbol; + } + + return SolanaTransactionModel( + isOutgoingTx: isOutgoing, + from: sender, + to: receiver, + id: signature, + amount: amount, + programId: SPLTokenProgramConst.tokenProgramId.address, + blockTimeInInt: blockTime?.toInt() ?? 0, + tokenSymbol: tokenSymbol ?? '', + fee: fee / SolanaUtils.lamportsPerSol, + ); } else { return null; } @@ -256,144 +330,6 @@ class SolanaWalletClient { return null; } - Future _parseNativeTransaction({ - required VersionedMessage message, - required ConfirmedTransactionMeta meta, - required int fee, - required double feeInSol, - required int feePayerIndex, - required String walletAddress, - required String signature, - required BigInt? blockTime, - }) async { - // Calculate total balance changes across all accounts - BigInt totalBalanceChange = BigInt.zero; - String? sender; - String? receiver; - - for (int i = 0; i < meta.preBalances.length; i++) { - final preBalance = meta.preBalances[i]; - final postBalance = meta.postBalances[i]; - final balanceChange = preBalance - postBalance; - - if (balanceChange > BigInt.zero) { - // This account sent funds - sender = message.accountKeys[i].address; - totalBalanceChange += balanceChange; - } else if (balanceChange < BigInt.zero) { - // This account received funds - receiver = message.accountKeys[i].address; - } - } - - // We subtract the fee from total balance change if the fee payer is the sender - if (sender == message.accountKeys[feePayerIndex].address) { - totalBalanceChange -= BigInt.from(fee); - } - - if (sender == null || receiver == null) { - return null; - } - - final amount = totalBalanceChange / BigInt.from(1e9); - final amountInSol = amount.abs().toDouble(); - - // Skip transactions with very small amounts (likely spam) - if (amountInSol < minValidAmount) { - return null; - } - - return SolanaTransactionModel( - isOutgoingTx: sender == walletAddress, - from: sender, - to: receiver, - id: signature, - amount: amountInSol, - programId: SystemProgramConst.programId.address, - tokenSymbol: 'SOL', - blockTimeInInt: blockTime?.toInt() ?? 0, - fee: feeInSol, - ); - } - - Future _parseSPLTokenTransaction({ - required VersionedMessage message, - required ConfirmedTransactionMeta meta, - required int fee, - required double feeInSol, - required CompiledInstruction instruction, - required String walletAddress, - required String signature, - required BigInt? blockTime, - String? splTokenSymbol, - }) async { - final preBalances = meta.preTokenBalances; - final postBalances = meta.postTokenBalances; - - double amount = 0.0; - bool isOutgoing = false; - String? mintAddress; - - double userPreAmount = 0.0; - if (preBalances != null && preBalances.isNotEmpty) { - for (final preBal in preBalances) { - if (preBal.owner?.address == walletAddress) { - userPreAmount = preBal.uiTokenAmount.uiAmount ?? 0.0; - - mintAddress = preBal.mint.address; - break; - } - } - } - - double userPostAmount = 0.0; - if (postBalances != null && postBalances.isNotEmpty) { - for (final postBal in postBalances) { - if (postBal.owner?.address == walletAddress) { - userPostAmount = postBal.uiTokenAmount.uiAmount ?? 0.0; - - mintAddress ??= postBal.mint.address; - break; - } - } - } - - final diff = userPreAmount - userPostAmount; - final rawAmount = diff.abs(); - - final amountInString = rawAmount.toStringAsFixed(6); - amount = double.parse(amountInString); - - isOutgoing = diff > 0; - - if (mintAddress == null && instruction.accounts.length >= 4) { - final mintIndex = instruction.accounts[3]; - mintAddress = message.accountKeys[mintIndex].address; - } - - final sender = message.accountKeys[instruction.accounts[0]].address; - final receiver = message.accountKeys[instruction.accounts[1]].address; - - String? tokenSymbol = splTokenSymbol; - - if (tokenSymbol == null && mintAddress != null) { - final token = await getTokenInfo(mintAddress); - tokenSymbol = token?.symbol; - } - - return SolanaTransactionModel( - isOutgoingTx: isOutgoing, - from: sender, - to: receiver, - id: signature, - amount: amount, - programId: SPLTokenProgramConst.tokenProgramId.address, - blockTimeInInt: blockTime?.toInt() ?? 0, - tokenSymbol: tokenSymbol ?? '', - fee: feeInSol, - ); - } - /// Load the Address's transactions into the account Future> fetchTransactions( SolAddress address, { @@ -433,28 +369,23 @@ class SolanaWalletClient { } })); - final versionedBatchResponses = - batchResponses.whereType(); + final versionedBatchResponses = batchResponses.whereType(); - final parsedTransactionsFutures = - versionedBatchResponses.map((tx) => parseTransaction( - txResponse: tx, - splTokenSymbol: splTokenSymbol, - walletAddress: walletAddress?.address ?? address.address, - )); + final parsedTransactionsFutures = versionedBatchResponses.map((tx) => parseTransaction( + txResponse: tx, + splTokenSymbol: splTokenSymbol, + walletAddress: walletAddress?.address ?? address.address, + )); final parsedTransactions = await Future.wait(parsedTransactionsFutures); - transactions.addAll( - parsedTransactions.whereType().toList()); + transactions.addAll(parsedTransactions.whereType().toList()); - // Only update UI if we have new valid transactions - if (parsedTransactions.isNotEmpty) { - onUpdate(List.from(transactions)); - } + // Calling the callback after each batch is processed, therefore passing the current list of transactions. + onUpdate(List.from(transactions)); if (i + batchSize < signatures.length) { - await Future.delayed(const Duration(milliseconds: 300)); + await Future.delayed(const Duration(milliseconds: 500)); } } @@ -515,8 +446,8 @@ class SolanaWalletClient { } Future fetchSPLTokenInfo(String mintAddress) async { - final programAddress = MetaplexTokenMetaDataProgramUtils.findMetadataPda( - mint: SolAddress(mintAddress)); + final programAddress = + MetaplexTokenMetaDataProgramUtils.findMetadataPda(mint: SolAddress(mintAddress)); final token = await _provider!.request( SolanaRPCGetMetadataAccount( @@ -537,9 +468,8 @@ class SolanaWalletClient { // iconPath = await _client.getIconImageFromTokenUri(metadata.uri); // } catch (_) {} - String filteredTokenSymbol = metadata.symbol - .replaceFirst(RegExp('^\\\$'), '') - .replaceAll('\u0000', ''); + String filteredTokenSymbol = + metadata.symbol.replaceFirst(RegExp('^\\\$'), '').replaceAll('\u0000', ''); return SPLToken.fromMetadata( name: metadata.name, @@ -655,8 +585,7 @@ class SolanaWalletClient { return message; } - Future _getFeeFromCompiledMessage( - Message message, Commitment commitment) async { + Future _getFeeFromCompiledMessage(Message message, Commitment commitment) async { final base64Message = base64Encode(message.serialize()); final fee = await getFeeForMessage(base64Message, commitment); @@ -795,8 +724,7 @@ class SolanaWalletClient { required SolAddress mintAddress, required bool shouldCreateATA, }) async { - final associatedTokenAccount = - AssociatedTokenAccountProgramUtils.associatedTokenAccount( + final associatedTokenAccount = AssociatedTokenAccountProgramUtils.associatedTokenAccount( mint: mintAddress, owner: ownerAddress, ); @@ -804,24 +732,19 @@ class SolanaWalletClient { SolanaAccountInfo? accountInfo; try { accountInfo = await _provider!.request( - SolanaRPCGetAccountInfo( - account: associatedTokenAccount.address, - commitment: Commitment.confirmed, - ), + SolanaRPCGetAccountInfo(account: associatedTokenAccount.address), ); } catch (e) { accountInfo = null; } - // If account exists, we return the associated token account + // If aacountInfo is null, signifies that the associatedTokenAccount has only been created locally and not been broadcasted to the blockchain. if (accountInfo != null) return associatedTokenAccount; if (!shouldCreateATA) return null; - final payerAddress = payerPrivateKey.publicKey().toAddress(); - final createAssociatedTokenAccount = AssociatedTokenAccountProgram.associatedTokenAccount( - payer: payerAddress, + payer: payerPrivateKey.publicKey().toAddress(), associatedToken: associatedTokenAccount.address, owner: ownerAddress, mint: mintAddress, @@ -830,23 +753,19 @@ class SolanaWalletClient { final blockhash = await _getLatestBlockhash(Commitment.confirmed); final transaction = SolanaTransaction( - payerKey: payerAddress, + payerKey: payerPrivateKey.publicKey().toAddress(), instructions: [createAssociatedTokenAccount], recentBlockhash: blockhash, - type: TransactionType.v0, ); - final serializedTransaction = await _signTransactionInternal( - ownerPrivateKey: payerPrivateKey, - transaction: transaction, - ); + transaction.sign([payerPrivateKey]); await sendTransaction( - serializedTransaction: serializedTransaction, + serializedTransaction: transaction.serializeString(), commitment: Commitment.confirmed, ); - // Wait for confirmation + // Delay for propagation on the blockchain for newly created associated token addresses await Future.delayed(const Duration(seconds: 2)); return associatedTokenAccount; @@ -867,8 +786,7 @@ class SolanaWalletClient { final amount = (inputAmount * math.pow(10, tokenDecimals)).toInt(); ProgramDerivedAddress? associatedSenderAccount; try { - associatedSenderAccount = - AssociatedTokenAccountProgramUtils.associatedTokenAccount( + associatedSenderAccount = AssociatedTokenAccountProgramUtils.associatedTokenAccount( mint: mintAddress, owner: ownerPrivateKey.publicKey().toAddress(), ); @@ -972,7 +890,7 @@ class SolanaWalletClient { }) async { /// Sign the transaction with the owner's private key. final ownerSignature = ownerPrivateKey.sign(transaction.serializeMessage()); - + transaction.addSignature(ownerPrivateKey.publicKey().toAddress(), ownerSignature); /// Serialize the transaction. @@ -1003,8 +921,7 @@ class SolanaWalletClient { if (uri.isEmpty || uri == '…') return null; try { - final client = ProxyWrapper().getHttpIOClient(); - final response = await client.get(Uri.parse(uri)); + final response = await httpClient.get(Uri.parse(uri)); final jsonResponse = json.decode(response.body) as Map; diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml index c91ca6efc..82b5a2bc0 100644 --- a/cw_solana/pubspec.yaml +++ b/cw_solana/pubspec.yaml @@ -33,9 +33,9 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.4.15 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 dependency_overrides: watcher: ^1.1.0 diff --git a/cw_tron/lib/tron_client.dart b/cw_tron/lib/tron_client.dart index cceec5327..ee93fbd53 100644 --- a/cw_tron/lib/tron_client.dart +++ b/cw_tron/lib/tron_client.dart @@ -5,7 +5,6 @@ import 'dart:developer'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/node.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_tron/pending_tron_transaction.dart'; import 'package:cw_tron/tron_abi.dart'; import 'package:cw_tron/tron_balance.dart'; @@ -14,12 +13,12 @@ import 'package:cw_tron/tron_token.dart'; import 'package:cw_tron/tron_transaction_model.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:http/http.dart'; import '.secrets.g.dart' as secrets; import 'package:on_chain/on_chain.dart'; class TronClient { - late final client = ProxyWrapper().getHttpIOClient(); - + final httpClient = Client(); TronProvider? _provider; // This is an internal tracker, so we don't have to "refetch". int _nativeTxEstimatedFee = 0; @@ -29,7 +28,7 @@ class TronClient { Future> fetchTransactions(String address, {String? contractAddress}) async { try { - final response = await client.get( + final response = await httpClient.get( Uri.https( "api.trongrid.io", "/v1/accounts/$address/transactions", @@ -62,7 +61,7 @@ class TronClient { Future> fetchTrc20ExcludedTransactions(String address) async { try { - final response = await client.get( + final response = await httpClient.get( Uri.https( "api.trongrid.io", "/v1/accounts/$address/transactions/trc20", diff --git a/cw_tron/lib/tron_http_provider.dart b/cw_tron/lib/tron_http_provider.dart index 420ff85b0..8a3301f87 100644 --- a/cw_tron/lib/tron_http_provider.dart +++ b/cw_tron/lib/tron_http_provider.dart @@ -1,22 +1,22 @@ import 'dart:convert'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; import 'package:on_chain/tron/tron.dart'; import '.secrets.g.dart' as secrets; class TronHTTPProvider implements TronServiceProvider { TronHTTPProvider( {required this.url, - this.defaultRequestTimeout = const Duration(seconds: 30)}); - + http.Client? client, + this.defaultRequestTimeout = const Duration(seconds: 30)}) + : client = client ?? http.Client(); @override final String url; - late final client = ProxyWrapper().getHttpIOClient(); + final http.Client client; final Duration defaultRequestTimeout; @override - Future> get(TronRequestDetails params, - [Duration? timeout]) async { + Future> get(TronRequestDetails params, [Duration? timeout]) async { final response = await client.get(Uri.parse(params.url(url)), headers: { 'Content-Type': 'application/json', if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey, @@ -27,16 +27,13 @@ class TronHTTPProvider implements TronServiceProvider { } @override - Future> post(TronRequestDetails params, - [Duration? timeout]) async { + Future> post(TronRequestDetails params, [Duration? timeout]) async { final response = await client .post(Uri.parse(params.url(url)), headers: { 'Content-Type': 'application/json', - if (url.contains("trongrid")) - 'TRON-PRO-API-KEY': secrets.tronGridApiKey, - if (url.contains("nownodes")) - 'api-key': secrets.tronNowNodesApiKey, + if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey, }, body: params.toRequestBody()) .timeout(timeout ?? defaultRequestTimeout); diff --git a/cw_tron/pubspec.yaml b/cw_tron/pubspec.yaml index 57c99286c..80ea7ee51 100644 --- a/cw_tron/pubspec.yaml +++ b/cw_tron/pubspec.yaml @@ -31,9 +31,9 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.4.15 + build_runner: ^2.3.3 mobx_codegen: ^2.1.1 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_wownero/lib/api/wallet.dart b/cw_wownero/lib/api/wallet.dart index a4ba8cbb2..20783490d 100644 --- a/cw_wownero/lib/api/wallet.dart +++ b/cw_wownero/lib/api/wallet.dart @@ -110,16 +110,7 @@ int getUnlockedBalance({int accountIndex = 0}) => int getCurrentHeight() => wownero.Wallet_blockChainHeight(wptr!); -int cachedNodeHeight = 0; -int getNodeHeightSync() { - (() async { - final wptrAddress = wptr!.address; - cachedNodeHeight = await Isolate.run(() async { - return wownero.Wallet_daemonBlockChainHeight(Pointer.fromAddress(wptrAddress)); - }); - })(); - return cachedNodeHeight; -} +int getNodeHeightSync() => wownero.Wallet_daemonBlockChainHeight(wptr!); bool isConnectedSync() => wownero.Wallet_connected(wptr!) != 0; @@ -163,7 +154,7 @@ Future setupNodeSync( } void startRefreshSync() { - // wownero.Wallet_refreshAsync(wptr!); + wownero.Wallet_refreshAsync(wptr!); wownero.Wallet_startRefresh(wptr!); } diff --git a/cw_wownero/lib/wownero_wallet.dart b/cw_wownero/lib/wownero_wallet.dart index 2befaa20d..e26672277 100644 --- a/cw_wownero/lib/wownero_wallet.dart +++ b/cw_wownero/lib/wownero_wallet.dart @@ -16,7 +16,6 @@ import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wownero_amount_format.dart'; @@ -184,14 +183,6 @@ abstract class WowneroWalletBase @override Future connectToNode({required Node node}) async { - String socksProxy = node.socksProxyAddress ?? ''; - printV("bootstrapped: ${CakeTor.instance.bootstrapped}"); - printV(" enabled: ${CakeTor.instance.enabled}"); - printV(" port: ${CakeTor.instance.port}"); - printV(" started: ${CakeTor.instance.started}"); - if (CakeTor.instance.enabled) { - socksProxy = "127.0.0.1:${CakeTor.instance.port}"; - } try { syncStatus = ConnectingSyncStatus(); await wownero_wallet.setupNode( @@ -201,7 +192,7 @@ abstract class WowneroWalletBase useSSL: node.isSSL, isLightWallet: false, // FIXME: hardcoded value - socksProxyAddress: socksProxy); + socksProxyAddress: node.socksProxyAddress); wownero_wallet.setTrustedDaemon(node.trusted); syncStatus = ConnectedSyncStatus(); diff --git a/cw_wownero/pubspec.lock b/cw_wownero/pubspec.lock index 0fa39123b..c2d5eeea7 100644 --- a/cw_wownero/pubspec.lock +++ b/cw_wownero/pubspec.lock @@ -5,23 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" url: "https://pub.dev" source: hosted - version: "76.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.3" + version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" url: "https://pub.dev" source: hosted - version: "6.11.0" + version: "4.7.0" args: dependency: transitive description: @@ -91,26 +86,26 @@ packages: dependency: "direct dev" description: name: build_resolvers - sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.2.10" built_collection: dependency: transitive description: @@ -219,10 +214,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" url: "https://pub.dev" source: hosted - version: "2.3.8" + version: "2.2.4" decimal: dependency: transitive description: @@ -341,10 +336,10 @@ packages: dependency: "direct dev" description: name: hive_generator - sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "1.1.3" http: dependency: "direct main" description: @@ -433,14 +428,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" - url: "https://pub.dev" - source: hosted - version: "0.1.3-main.0" matcher: dependency: transitive description: @@ -485,16 +472,16 @@ packages: dependency: "direct dev" description: name: mobx_codegen - sha256: e0abbbc651a69550440f6b65c99ec222a1e2a4afd7baec8ba0f3088c7ca582a8 + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.7.1" + version: "2.3.0" monero: dependency: "direct main" description: path: "impls/monero.dart" - ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 - resolved-ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 + ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 + resolved-ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 url: "https://github.com/mrcyjanek/monero_c" source: git version: "0.0.0" @@ -683,37 +670,27 @@ packages: socks5_proxy: dependency: transitive description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: transitive - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" url: "https://pub.dev" source: hosted - version: "1.3.5" + version: "1.3.3" source_span: dependency: transitive description: @@ -774,19 +751,10 @@ packages: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" - tor_binary: - dependency: transitive - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" + version: "1.0.2" tuple: dependency: transitive description: @@ -876,5 +844,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.27.4" diff --git a/cw_wownero/pubspec.yaml b/cw_wownero/pubspec.yaml index 4fda054b5..7b9ec4c41 100644 --- a/cw_wownero/pubspec.yaml +++ b/cw_wownero/pubspec.yaml @@ -2,6 +2,7 @@ name: cw_wownero description: A new flutter plugin project. version: 0.0.1 publish_to: none +author: Cake Wallet homepage: https://cakewallet.com environment: @@ -24,17 +25,17 @@ dependencies: monero: git: url: https://github.com/mrcyjanek/monero_c - ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 # monero_c hash + ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 # monero_c hash path: impls/monero.dart mutex: ^3.1.0 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 - build_resolvers: ^2.4.4 + build_runner: ^2.4.7 + build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 + hive_generator: ^1.1.3 dependency_overrides: watcher: ^1.1.0 diff --git a/cw_zano/pubspec.lock b/cw_zano/pubspec.lock index 41edf154e..ec99b272a 100644 --- a/cw_zano/pubspec.lock +++ b/cw_zano/pubspec.lock @@ -5,23 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" url: "https://pub.dev" source: hosted - version: "76.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.3" + version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" url: "https://pub.dev" source: hosted - version: "6.11.0" + version: "4.7.0" args: dependency: transitive description: @@ -91,26 +86,26 @@ packages: dependency: "direct dev" description: name: build_resolvers - sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.2.10" built_collection: dependency: transitive description: @@ -219,10 +214,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" url: "https://pub.dev" source: hosted - version: "2.3.8" + version: "2.2.4" decimal: dependency: "direct main" description: @@ -338,10 +333,10 @@ packages: dependency: "direct dev" description: name: hive_generator - sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "1.1.3" http: dependency: "direct main" description: @@ -438,14 +433,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" - url: "https://pub.dev" - source: hosted - version: "0.1.3-main.0" matcher: dependency: transitive description: @@ -490,16 +477,16 @@ packages: dependency: "direct dev" description: name: mobx_codegen - sha256: e0abbbc651a69550440f6b65c99ec222a1e2a4afd7baec8ba0f3088c7ca582a8 + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.7.1" + version: "2.3.0" monero: dependency: "direct main" description: path: "impls/monero.dart" - ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 - resolved-ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 + ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 + resolved-ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 url: "https://github.com/mrcyjanek/monero_c" source: git version: "0.0.0" @@ -680,37 +667,27 @@ packages: socks5_proxy: dependency: transitive description: - path: "." - ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - resolved-ref: "27ad7c2efae8d7460325c74b90f660085cbd0685" - url: "https://github.com/LacticWhale/socks_dart" - source: git - version: "2.1.0" - socks_socket: - dependency: transitive - description: - path: "." - ref: e6232c53c1595469931ababa878759a067c02e94 - resolved-ref: e6232c53c1595469931ababa878759a067c02e94 - url: "https://github.com/sneurlax/socks_socket" - source: git - version: "1.1.1" + name: socks5_proxy + sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053" + url: "https://pub.dev" + source: hosted + version: "1.0.6" source_gen: dependency: transitive description: name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" url: "https://pub.dev" source: hosted - version: "1.3.5" + version: "1.3.3" source_span: dependency: transitive description: @@ -775,15 +752,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" - tor_binary: - dependency: transitive - description: - path: "." - ref: cb811c610871a9517d47134b87c2f590c15c96c5 - resolved-ref: cb811c610871a9517d47134b87c2f590c15c96c5 - url: "https://github.com/MrCyjaneK/flutter-tor_binary" - source: git - version: "4.7.14" tuple: dependency: transitive description: @@ -873,5 +841,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.27.4" diff --git a/cw_zano/pubspec.yaml b/cw_zano/pubspec.yaml index 529fe04eb..ff2c1e9a6 100644 --- a/cw_zano/pubspec.yaml +++ b/cw_zano/pubspec.yaml @@ -2,6 +2,7 @@ name: cw_zano description: A new flutter plugin project. version: 0.0.1 publish_to: none +author: Cake Wallet homepage: https://cakewallet.com environment: @@ -25,15 +26,15 @@ dependencies: monero: git: url: https://github.com/mrcyjanek/monero_c - ref: a27fbcb24d91143715ed930a05aaa4d853fba1f2 # monero_c hash + ref: b335585a7fb94b315eb52bd88f2da6d3489fa508 # monero_c hash path: impls/monero.dart dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.15 + build_runner: ^2.4.7 mobx_codegen: ^2.1.1 - build_resolvers: ^2.4.4 - hive_generator: ^2.0.1 + build_resolvers: ^2.0.9 + hive_generator: ^1.1.3 dependency_overrides: watcher: ^1.1.0 diff --git a/docs/builds/ANDROID.md b/docs/builds/ANDROID.md index d7bc584ad..226883679 100644 --- a/docs/builds/ANDROID.md +++ b/docs/builds/ANDROID.md @@ -18,8 +18,8 @@ In order to build the latest version of Cake Wallet, simply run the following: git clone --branch main https://github.com/cake-tech/cake_wallet.git # NOTE: Replace `main` with the latest release tag available at https://github.com/cake-tech/cake_wallet/releases/latest. cd cake_wallet -# docker build -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly . # Uncomment to build the docker image yourself instead of pulling it from the registry -docker run -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly bash -x << EOF +# docker build -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 . # Uncomment to build the docker image yourself instead of pulling it from the registry +docker run -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 bash -x << EOF set -x -e pushd scripts/android source ./app_env.sh cakewallet diff --git a/docs/builds/IOS.md b/docs/builds/IOS.md index 1d23b917c..44abaa805 100644 --- a/docs/builds/IOS.md +++ b/docs/builds/IOS.md @@ -7,7 +7,7 @@ The following are the system requirements to build Cake Wallet for your iOS devi ```txt macOS 15.3.1 Xcode 16.2 -Flutter 3.27.0 +Flutter 3.27.4 ``` NOTE: Newer versions of macOS and Xcode may also work, but have not been confirmed to work by the Cake team. @@ -43,9 +43,9 @@ To enable iOS build support for Xcode, perform the following: ### 3. Installing Flutter -Install Flutter, specifically version `3.27.0` by following the [official docs](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download). +Install Flutter, specifically version `3.27.4` by following the [official docs](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download). -NOTE: as `3.27.0` is not the latest version, you'll need to download it from instead of the link in the docs above. +NOTE: as `3.27.4` is not the latest version, you'll need to download it from instead of the link in the docs above. ### 4. Installing Rust @@ -65,7 +65,7 @@ The output of this command should appear like this, indicating successful instal ```zsh Doctor summary (to see all details, run flutter doctor -v): -[✓] Flutter (Channel stable, 3.27.0, on macOS 15.x.x) +[✓] Flutter (Channel stable, 3.27.4, on macOS 15.x.x) [✓] Xcode - develop for iOS and macOS (Xcode 16.2) ``` diff --git a/docs/builds/LINUX.md b/docs/builds/LINUX.md index 0f438a1d6..a97a269a5 100644 --- a/docs/builds/LINUX.md +++ b/docs/builds/LINUX.md @@ -20,8 +20,8 @@ In order to build the latest version of Cake Wallet, simply run the following: git clone --branch main https://github.com/cake-tech/cake_wallet.git # NOTE: Replace `main` with the latest release tag available at https://github.com/cake-tech/cake_wallet/releases/latest. cd cake_wallet -# docker build -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly . # Uncomment to build the docker image yourself instead of pulling it from the registry -docker run --privileged -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly bash -x << EOF +# docker build -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 . # Uncomment to build the docker image yourself instead of pulling it from the registry +docker run --privileged -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1 bash -x << EOF set -x -e pushd scripts ./gen_android_manifest.sh diff --git a/docs/builds/MACOS.md b/docs/builds/MACOS.md index 7e0f39aab..46a9842a4 100644 --- a/docs/builds/MACOS.md +++ b/docs/builds/MACOS.md @@ -7,7 +7,7 @@ The following are the system requirements to build Cake Wallet for your macOS de ```txt macOS 15.3.1 Xcode 16.2 -Flutter 3.27.0 +Flutter 3.27.4 ``` ### 1. Installing dependencies @@ -34,9 +34,9 @@ sudo xcodebuild -runFirstLaunch ### 3. Installing Flutter -Install Flutter, specifically version `3.27.0` by following the [official docs](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download). +Install Flutter, specifically version `3.27.4` by following the [official docs](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download). -NOTE: as `3.27.0` is not the latest version, you'll need to download it from instead of the link in the docs above. +NOTE: as `3.27.4` is not the latest version, you'll need to download it from instead of the link in the docs above. ### 4. Installing Rust @@ -56,7 +56,7 @@ The output of this command should appear like this, indicating successful instal ```zsh Doctor summary (to see all details, run flutter doctor -v): -[✓] Flutter (Channel stable, 3.27.0, on macOS 15.x.x) +[✓] Flutter (Channel stable, 3.27.4, on macOS 15.x.x) ... [✓] Xcode - develop for iOS and macOS (Xcode 16.2) ... diff --git a/docs/builds/WINDOWS.md b/docs/builds/WINDOWS.md index 7a86dac49..4fec78dc0 100644 --- a/docs/builds/WINDOWS.md +++ b/docs/builds/WINDOWS.md @@ -6,18 +6,18 @@ The following are the system requirements to build Cake Wallet for your Windows ```txt Windows 10 or later (64-bit), x86-64 based -Flutter 3.27.0 +Flutter 3.27.4 ``` ### 1. Installing Flutter -Install Flutter, specifically version `3.27.0` by following the [official docs](https://docs.flutter.dev/get-started/install/windows). +Install Flutter, specifically version `3.27.4` by following the [official docs](https://docs.flutter.dev/get-started/install/windows). In order for Flutter to function, you'll also need to enable Developer Mode: Start Menu > search for "Run" > type `ms-settings:developers`, and turn on Developer Mode. -NOTE: as `3.27.0` is not the latest version, you'll need to download it from instead of the link in the docs above. +NOTE: as `3.27.4` is not the latest version, you'll need to download it from instead of the link in the docs above. ### 2. Install Development Tools diff --git a/integration_test/robots/new_wallet_type_page_robot.dart b/integration_test/robots/new_wallet_type_page_robot.dart index eb1a1900a..89fc8d390 100644 --- a/integration_test/robots/new_wallet_type_page_robot.dart +++ b/integration_test/robots/new_wallet_type_page_robot.dart @@ -1,6 +1,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; -import 'package:cake_wallet/themes/core/material_base_theme.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/integration_test/robots/wallet_keys_robot.dart b/integration_test/robots/wallet_keys_robot.dart index 38a605b9d..189929737 100644 --- a/integration_test/robots/wallet_keys_robot.dart +++ b/integration_test/robots/wallet_keys_robot.dart @@ -70,10 +70,7 @@ class WalletKeysAndSeedPageRobot { if (walletType == WalletType.bitcoin || walletType == WalletType.litecoin || walletType == WalletType.bitcoinCash) { - final seedWords = appStore.wallet!.seed!.split(" "); - for (var seedWord in seedWords) { - commonTestCases.hasTextAtLestOnce(seedWord); - } + commonTestCases.hasText(appStore.wallet!.seed!); tester.printToConsole('$walletName wallet has seeds properly displayed'); } @@ -81,14 +78,10 @@ class WalletKeysAndSeedPageRobot { walletType == WalletType.solana || walletType == WalletType.tron) { if (hasSeed) { - final seedWords = appStore.wallet!.seed!.split(" "); - for (var seedWord in seedWords) { - commonTestCases.hasTextAtLestOnce(seedWord); - } + commonTestCases.hasText(appStore.wallet!.seed!); tester.printToConsole('$walletName wallet has seeds properly displayed'); } if (hasPrivateKey) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(appStore.wallet!.privateKey!); tester.printToConsole('$walletName wallet has private key properly displayed'); } @@ -96,19 +89,14 @@ class WalletKeysAndSeedPageRobot { if (walletType == WalletType.nano || walletType == WalletType.banano) { if (hasSeed) { - final seedWords = appStore.wallet!.seed!.split(" "); - for (var seedWord in seedWords) { - commonTestCases.hasTextAtLestOnce(seedWord); - } + commonTestCases.hasText(appStore.wallet!.seed!); tester.printToConsole('$walletName wallet has seeds properly displayed'); } if (hasHexSeed) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(appStore.wallet!.hexSeed!); tester.printToConsole('$walletName wallet has hexSeed properly displayed'); } if (hasPrivateKey) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(appStore.wallet!.privateKey!); tester.printToConsole('$walletName wallet has private key properly displayed'); } @@ -141,39 +129,35 @@ class WalletKeysAndSeedPageRobot { final hasSeedLegacy = Polyseed.isValidSeed(seed); if (hasPublicSpendKey) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(keys.publicSpendKey); tester.printToConsole('$walletName wallet has public spend key properly displayed'); } if (hasPrivateSpendKey) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(keys.privateSpendKey); tester.printToConsole('$walletName wallet has private spend key properly displayed'); } if (hasPublicViewKey) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(keys.publicViewKey); tester.printToConsole('$walletName wallet has public view key properly displayed'); } if (hasPrivateViewKey) { - await commonTestCases.tapItemByKey('wallet_keys_page_keys'); commonTestCases.hasText(keys.privateViewKey); tester.printToConsole('$walletName wallet has private view key properly displayed'); } if (hasSeeds) { - await commonTestCases.tapItemByKey('wallet_keys_page_seed'); - final seedWords = seed.split(" "); - for (var seedWord in seedWords) { - commonTestCases.hasTextAtLestOnce(seedWord); - } + await commonTestCases.dragUntilVisible( + '${walletName}_wallet_seed_item_key', + 'wallet_keys_page_credentials_list_view_key', + ); + commonTestCases.hasText(seed); tester.printToConsole('$walletName wallet has seeds properly displayed'); } if (hasSeedLegacy) { - await commonTestCases.tapItemByKey('wallet_keys_page_seed_legacy'); - final seedWords = legacySeed.split(" "); - for (var seedWord in seedWords) { - commonTestCases.hasTextAtLestOnce(seedWord); - } + await commonTestCases.dragUntilVisible( + '${walletName}_wallet_seed_legacy_item_key', + 'wallet_keys_page_credentials_list_view_key', + ); + commonTestCases.hasText(legacySeed); tester.printToConsole('$walletName wallet has legacy seeds properly displayed'); } } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index abbd40673..3d39d589e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -76,7 +76,6 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - payjoin_flutter (0.23.0) - permission_handler_apple (9.3.0): - Flutter - reown_yttrium (0.0.1): @@ -127,7 +126,6 @@ DEPENDENCIES: - integration_test (from `.symlinks/plugins/integration_test/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - - payjoin_flutter (from `.symlinks/plugins/payjoin_flutter/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - reown_yttrium (from `.symlinks/plugins/reown_yttrium/ios`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) @@ -188,8 +186,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" - payjoin_flutter: - :path: ".symlinks/plugins/payjoin_flutter/ios" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" reown_yttrium: @@ -212,43 +208,40 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: - connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d + connectivity_plus: 481668c94744c30c53b8895afb39159d1e619bdf CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90 - cw_decred: 9c0e1df74745b51a1289ec5e91fb9e24b68fa14a - cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3 - device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 - device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 - devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926 + cw_decred: a02cf30175a46971c1e2fa22c48407534541edc6 + cw_mweb: 3aea2fb35b2bd04d8b2d21b83216f3b8fb768d85 + device_display_brightness: 04374ebd653619292c1d996f00f42877ea19f17f + device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 + devicelocale: bd64aa714485a8afdaded0892c1e7d5b7f680cf8 DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - fast_scanner: 44c00940355a51258cd6c2085734193cd23d95bc - file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 + fast_scanner: 2cb1ad3e69e645e9980fb4961396ce5804caa3e3 + file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 - flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb - flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f - flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 - flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be - fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f - in_app_review: a31b5257259646ea78e0e35fc914979b0031d011 - integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 + flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 + flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f + flutter_mailer: 3a8cd4f36c960fb04528d5471097270c19fec1c4 + flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418 + fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 + in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457 + integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - payjoin_flutter: d9d4c8aa16bd5dfedb9b21d0edc8199e0187d96e - permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 - reown_yttrium: c0e87e5965fa60a3559564cc35cffbba22976089 + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8 - sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 - share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12 + sensitive_clipboard: 161e9abc3d56b3131309d8a321eb4690a803c16b + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + sp_scanner: b1bc9321690980bdb44bba7ec85d5543e716d1b5 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - uni_links: d97da20c7701486ba192624d99bffaaffcfc298a - universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e - YttriumWrapper: 31e937fe9fbe0f1314d2ca6be9ce9b379a059966 + uni_links: ed8c961e47ed9ce42b6d91e1de8049e38a4b3152 + universal_ble: ff19787898040d721109c6324472e5dd4bc86adc + url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 PODFILE CHECKSUM: 5296465b1c6d14d506230356756826012f65d97a diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 40868aa9f..f27ef8d4f 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -327,7 +327,5 @@ UIViewControllerBasedStatusBarAppearance - FlutterDeepLinkingEnabled - diff --git a/lib/anonpay/anonpay_api.dart b/lib/anonpay/anonpay_api.dart index 6f401ae3f..acab662d1 100644 --- a/lib/anonpay/anonpay_api.dart +++ b/lib/anonpay/anonpay_api.dart @@ -6,9 +6,8 @@ import 'package:cake_wallet/anonpay/anonpay_status_response.dart'; import 'package:cake_wallet/core/fiat_conversion_service.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:http/http.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; @@ -21,21 +20,17 @@ class AnonPayApi { final WalletBase wallet; static const anonpayRef = secrets.anonPayReferralCode; + static const onionApiAuthority = 'tqzngtf2hybjbexznel6dhgsvbynjzezoybvtv6iofomx7gchqfssgqd.onion'; static const clearNetAuthority = 'trocador.app'; - // static const onionApiAuthority = 'tqzngtf2hybjbexznel6dhgsvbynjzezoybvtv6iofomx7gchqfssgqd.onion'; - static const onionApiAuthority = clearNetAuthority; static const markup = secrets.trocadorExchangeMarkup; static const anonPayPath = '/anonpay'; static const anonPayStatus = '/anonpay/status'; static const coinPath = 'api/coin'; - static final apiKey = isMoneroOnly ? secrets.trocadorMoneroApiKey : secrets.trocadorApiKey; + static const apiKey = secrets.trocadorApiKey; Future paymentStatus(String id) async { - final response = await ProxyWrapper().get( - clearnetUri: Uri.https(clearNetAuthority, "$anonPayStatus/$id"), - onionUri: Uri.https(onionApiAuthority, "$anonPayStatus/$id"), - ); - + final authority = await _getAuthority(); + final response = await get(Uri.https(authority, "$anonPayStatus/$id")); final responseJSON = json.decode(response.body) as Map; final status = responseJSON['Status'] as String; final fiatAmount = responseJSON['Fiat_Amount'] as double?; @@ -74,11 +69,10 @@ class AnonPayApi { if (request.fiatEquivalent != null) { body['fiat_equiv'] = request.fiatEquivalent; } - final response = await ProxyWrapper().get( - clearnetUri: Uri.https(clearNetAuthority, anonPayPath, body), - onionUri: Uri.https(onionApiAuthority, anonPayPath, body), - ); - + final authority = await _getAuthority(); + + final response = await get(Uri.https(authority, anonPayPath, body)); + final responseJSON = json.decode(response.body) as Map; final id = responseJSON['ID'] as String; final url = responseJSON['url'] as String; @@ -152,16 +146,17 @@ class AnonPayApi { 'name': cryptoCurrency.name, }; - final response = await ProxyWrapper().get( - clearnetUri: Uri.https(clearNetAuthority, coinPath, params), - onionUri: Uri.https(onionApiAuthority, coinPath, params), - ); - - final responseJSON = json.decode(response.body) as List; + final String apiAuthority = await _getAuthority(); + final uri = Uri.https(apiAuthority, coinPath, params); + + final response = await get(uri); + if (response.statusCode != 200) { throw Exception('Unexpected http status: ${response.statusCode}'); } + final responseJSON = json.decode(response.body) as List; + if (responseJSON.isEmpty) { throw Exception('No data'); } @@ -202,4 +197,17 @@ class AnonPayApi { return tag.toLowerCase(); } } + + Future _getAuthority() async { + try { + if (useTorOnly) { + return onionApiAuthority; + } + final uri = Uri.https(onionApiAuthority, '/anonpay'); + await get(uri); + return onionApiAuthority; + } catch (e) { + return clearNetAuthority; + } + } } diff --git a/lib/anypay/anypay_api.dart b/lib/anypay/anypay_api.dart index 20187484b..0b81d24c2 100644 --- a/lib/anypay/anypay_api.dart +++ b/lib/anypay/anypay_api.dart @@ -1,8 +1,8 @@ import 'dart:convert'; import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:flutter/foundation.dart'; +import 'package:http/http.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/anypay/any_pay_payment.dart'; import 'package:cake_wallet/anypay/any_pay_trasnaction.dart'; @@ -53,12 +53,8 @@ class AnyPayApi { final body = { 'chain': chainByScheme(scheme), 'currency': currencyByScheme(scheme).title}; - final response = await ProxyWrapper().post( - clearnetUri: url, - headers: headers, - body: json.encode(body), - ); - + final response = await post(url, headers: headers, body: utf8.encode(json.encode(body))); + if (response.statusCode != 200) { await ExceptionHandler.onError(FlutterErrorDetails(exception: response)); throw Exception('Unexpected response http code: ${response.statusCode}'); @@ -83,12 +79,7 @@ class AnyPayApi { 'chain': chain, 'currency': currency, 'transactions': transactions.map((tx) => {'tx': tx.tx, 'tx_hash': tx.id, 'tx_key': tx.key}).toList()}; - final response = await ProxyWrapper().post( - clearnetUri: Uri.parse(uri), - headers: headers, - body: json.encode(body), - ); - + final response = await post(Uri.parse(uri), headers: headers, body: utf8.encode(json.encode(body))); if (response.statusCode == 400) { final decodedBody = json.decode(response.body) as Map; throw Exception(decodedBody['message'] as String? ?? 'Unexpected response\nError code: 400'); diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 131bc3a02..cbdb343fe 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -747,6 +747,5 @@ class CWBitcoin extends Bitcoin { final _wallet = wallet as ElectrumWallet; (_wallet.walletAddresses as BitcoinWalletAddresses).payjoinManager.cleanupSessions(); (_wallet.walletAddresses as BitcoinWalletAddresses).currentPayjoinReceiver = null; - (_wallet.walletAddresses as BitcoinWalletAddresses).payjoinEndpoint = null; } } diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index f57cc5472..55ef5e6c3 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -64,7 +64,6 @@ abstract class BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode}) async => null; } diff --git a/lib/buy/buy_quote.dart b/lib/buy/buy_quote.dart index da854faaf..1805b7e1a 100644 --- a/lib/buy/buy_quote.dart +++ b/lib/buy/buy_quote.dart @@ -50,7 +50,6 @@ class Quote extends SelectableOption { this.rampName, this.rampIconPath, this.limits, - this.customPaymentMethodType, }) : super(title: provider.isAggregator ? rampName ?? '' : provider.title); final double rate; @@ -69,7 +68,6 @@ class Quote extends SelectableOption { bool _isBestRate = false; bool isBuyAction; Limits? limits; - String? customPaymentMethodType; late FiatCurrency _fiatCurrency; late CryptoCurrency _cryptoCurrency; @@ -132,7 +130,7 @@ class Quote extends SelectableOption { set setLimits(Limits limits) => this.limits = limits; factory Quote.fromOnramperJson(Map json, bool isBuyAction, - Map metaData, PaymentType paymentType, String? customPaymentMethodType) { + Map metaData, PaymentType paymentType) { final rate = _toDouble(json['rate']) ?? 0.0; final networkFee = _toDouble(json['networkFee']) ?? 0.0; final transactionFee = _toDouble(json['transactionFee']) ?? 0.0; @@ -185,7 +183,6 @@ class Quote extends SelectableOption { rampName: rampName, rampIconPath: rampIconPath, paymentType: paymentType, - customPaymentMethodType: customPaymentMethodType, quoteId: json['quoteId'] as String? ?? '', recommendations: enumRecommendations, provider: ProvidersHelper.getProviderByType(ProviderType.onramper)!, diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index eed527cf1..267406893 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -10,7 +10,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -18,6 +17,7 @@ import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class DFXBuyProvider extends BuyProvider { @@ -100,12 +100,11 @@ class DFXBuyProvider extends BuyProvider { }); final uri = Uri.https(_baseUrl, _authPath); - final response = await ProxyWrapper().post( - clearnetUri: uri, + var response = await http.post( + uri, headers: {'Content-Type': 'application/json'}, body: requestBody, ); - if (response.statusCode == 201) { final responseBody = jsonDecode(response.body); @@ -138,10 +137,8 @@ class DFXBuyProvider extends BuyProvider { final url = Uri.https(_baseUrl, '/v1/fiat'); try { - final response = await ProxyWrapper().get( - clearnetUri: url, - headers: {'accept': 'application/json'}); - + final response = await http.get(url, headers: {'accept': 'application/json'}); + if (response.statusCode == 200) { final data = jsonDecode(response.body) as List; for (final item in data) { @@ -163,8 +160,8 @@ class DFXBuyProvider extends BuyProvider { final url = Uri.https(_baseUrl, '/v1/asset', {'blockchains': blockchain}); try { - final response = await ProxyWrapper().get(clearnetUri: url, headers: {'accept': 'application/json'}); - + final response = await http.get(url, headers: {'accept': 'application/json'}); + if (response.statusCode == 200) { final responseData = jsonDecode(response.body); @@ -234,7 +231,6 @@ class DFXBuyProvider extends BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode}) async { /// if buying with any currency other than eur or chf then DFX is not supported @@ -274,12 +270,7 @@ class DFXBuyProvider extends BuyProvider { }); try { - final response = await ProxyWrapper().put( - clearnetUri: url, - headers: headers, - body: body, - ); - + final response = await http.put(url, headers: headers, body: body); final responseData = jsonDecode(response.body); if (response.statusCode == 200) { @@ -382,7 +373,7 @@ class DFXBuyProvider extends BuyProvider { case 'Instant': return PaymentType.sepa; default: - return PaymentType.unknown; + return PaymentType.all; } } diff --git a/lib/buy/kryptonim/kryptonim.dart b/lib/buy/kryptonim/kryptonim.dart index 1d2d10f58..6e00a7e07 100644 --- a/lib/buy/kryptonim/kryptonim.dart +++ b/lib/buy/kryptonim/kryptonim.dart @@ -9,10 +9,10 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; import 'dart:developer'; +import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class KryptonimBuyProvider extends BuyProvider { @@ -74,14 +74,9 @@ class KryptonimBuyProvider extends BuyProvider { }); try { - final response = await ProxyWrapper().post( - clearnetUri: url, - headers: headers, - body: body, - ); + final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 401) { - return jsonDecode(response.body) as Map; } else { return {}; @@ -118,7 +113,6 @@ class KryptonimBuyProvider extends BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode, }) async { log('Kryptonim: Fetching quote: ${isBuyAction ? cryptoCurrency : fiatCurrency} -> ${isBuyAction ? fiatCurrency : cryptoCurrency}, amount: $amount'); @@ -155,7 +149,7 @@ class KryptonimBuyProvider extends BuyProvider { final selectedPaymentType = PaymentMethod.getPaymentTypeId(selectedPaymentMethod['payment_method'] as String?); - final quote = Quote.fromKryptonimJson(selectedPaymentMethod, isBuyAction, selectedPaymentType ?? PaymentType.unknown); + final quote = Quote.fromKryptonimJson(selectedPaymentMethod, isBuyAction, selectedPaymentType); quote.setFiatCurrency = fiatCurrency; quote.setCryptoCurrency = cryptoCurrency; diff --git a/lib/buy/meld/meld_buy_provider.dart b/lib/buy/meld/meld_buy_provider.dart index 002ab0465..e96a3575c 100644 --- a/lib/buy/meld/meld_buy_provider.dart +++ b/lib/buy/meld/meld_buy_provider.dart @@ -8,13 +8,13 @@ import 'package:cake_wallet/buy/payment_method.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; import 'dart:developer'; +import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class MeldBuyProvider extends BuyProvider { @@ -71,8 +71,8 @@ class MeldBuyProvider extends BuyProvider { final url = Uri.https(_baseUrl, path, params); try { - final response = await ProxyWrapper().get( - clearnetUri: url, + final response = await http.get( + url, headers: { 'Authorization': _isProduction ? '' : _testApiKey, 'Meld-Version': '2023-12-19', @@ -80,7 +80,6 @@ class MeldBuyProvider extends BuyProvider { 'content-type': 'application/json', }, ); - if (response.statusCode == 200) { final data = jsonDecode(response.body) as List; @@ -105,7 +104,6 @@ class MeldBuyProvider extends BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode}) async { String? paymentMethod; if (paymentType != null && paymentType != PaymentType.all) { @@ -131,12 +129,7 @@ class MeldBuyProvider extends BuyProvider { }); try { - final response = await ProxyWrapper().post( - clearnetUri: url, - headers: headers, - body: body, - ); - + final response = await http.post(url, headers: headers, body: body); if (response.statusCode == 200) { final data = jsonDecode(response.body) as Map; diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index 1f9ab1bb1..6c568886f 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -14,24 +14,24 @@ import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cake_wallet/themes/core/material_base_theme.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart'; import 'package:url_launcher/url_launcher.dart'; class MoonPayProvider extends BuyProvider { MoonPayProvider({ - required AppStore appStore, + required SettingsStore settingsStore, required WalletBase wallet, bool isTestEnvironment = false, }) : baseSellUrl = isTestEnvironment ? _baseSellTestUrl : _baseSellProductUrl, baseBuyUrl = isTestEnvironment ? _baseBuyTestUrl : _baseBuyProductUrl, - this._appStore = appStore, + this._settingsStore = settingsStore, super( wallet: wallet, isTestEnvironment: isTestEnvironment, @@ -41,7 +41,7 @@ class MoonPayProvider extends BuyProvider { supportedFiatList: supportedFiatToCryptoPairs( notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto)); - final AppStore _appStore; + final SettingsStore _settingsStore; static const _baseSellTestUrl = 'sell-sandbox.moonpay.com'; static const _baseSellProductUrl = 'sell.moonpay.com'; @@ -86,24 +86,24 @@ class MoonPayProvider extends BuyProvider { static String get _exchangeHelperApiKey => secrets.exchangeHelperApiKey; - static String themeToMoonPayTheme(MaterialThemeBase theme) { + static String themeToMoonPayTheme(ThemeBase theme) { switch (theme.type) { + case ThemeType.bright: case ThemeType.light: return 'light'; case ThemeType.dark: return 'dark'; + case ThemeType.oled: + return 'dark'; } } Future getMoonpaySignature(String query) async { final uri = Uri.https(_cIdBaseUrl, "/api/moonpay"); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: {'Content-Type': 'application/json', 'x-api-key': _exchangeHelperApiKey}, - body: json.encode({'query': query}), - ); - + final response = await post(uri, + headers: {'Content-Type': 'application/json', 'x-api-key': _exchangeHelperApiKey}, + body: json.encode({'query': query})); if (response.statusCode == 200) { return (jsonDecode(response.body) as Map)['signature'] as String; @@ -123,11 +123,7 @@ class MoonPayProvider extends BuyProvider { final url = Uri.https(_baseUrl, path, params); try { - final response = await ProxyWrapper().get( - clearnetUri: url, - headers: {'accept': 'application/json'}, - ); - + final response = await get(url, headers: {'accept': 'application/json'}); if (response.statusCode == 200) { return jsonDecode(response.body) as Map; } else { @@ -166,7 +162,6 @@ class MoonPayProvider extends BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode}) async { String? paymentMethod; @@ -198,8 +193,8 @@ class MoonPayProvider extends BuyProvider { final path = '$_currenciesPath/$formattedCryptoCurrency$quotePath'; final url = Uri.https(_baseUrl, path, params); try { - final response = await ProxyWrapper().get(clearnetUri: url); - + final response = await get(url); + if (response.statusCode == 200) { final data = jsonDecode(response.body) as Map; @@ -241,9 +236,9 @@ class MoonPayProvider extends BuyProvider { required String cryptoCurrencyAddress, String? countryCode}) async { final Map params = { - 'theme': themeToMoonPayTheme(_appStore.themeStore.currentTheme), - 'language': _appStore.settingsStore.languageCode, - 'colorCode': _appStore.themeStore.currentTheme.isDark + 'theme': themeToMoonPayTheme(_settingsStore.currentTheme), + 'language': _settingsStore.languageCode, + 'colorCode': _settingsStore.currentTheme.type == ThemeType.dark ? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}' : '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}', 'baseCurrencyCode': isBuyAction ? quote.fiatCurrency.name : quote.cryptoCurrency.name, @@ -264,6 +259,7 @@ class MoonPayProvider extends BuyProvider { try { final uri = await requestMoonPayUrl( walletAddress: cryptoCurrencyAddress, + settingsStore: _settingsStore, isBuyAction: isBuyAction, amount: amount.toString(), params: params); @@ -292,6 +288,7 @@ class MoonPayProvider extends BuyProvider { Future requestMoonPayUrl({ required String walletAddress, + required SettingsStore settingsStore, required bool isBuyAction, required Map params, String? amount, @@ -313,8 +310,7 @@ class MoonPayProvider extends BuyProvider { Future findOrderById(String id) async { final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey; final uri = Uri.parse(url); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); if (response.statusCode != 200) { throw BuyException(title: providerDescription, content: 'Transaction $id is not found!'); @@ -414,7 +410,7 @@ class MoonPayProvider extends BuyProvider { case 'yellow_card_bank_transfer': return PaymentType.yellowCardBankTransfer; default: - return PaymentType.unknown; + return PaymentType.all; } } } diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index 80c9a6326..dc9812d1d 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -8,17 +8,17 @@ import 'package:cake_wallet/buy/pairs_utils.dart'; import 'package:cake_wallet/buy/payment_method.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/themes/core/theme_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class OnRamperBuyProvider extends BuyProvider { - OnRamperBuyProvider(this._themeStore, + OnRamperBuyProvider(this._settingsStore, {required WalletBase wallet, bool isTestEnvironment = false}) : super(wallet: wallet, isTestEnvironment: isTestEnvironment, @@ -33,15 +33,12 @@ class OnRamperBuyProvider extends BuyProvider { static const quotes = '/quotes'; static const paymentTypes = '/payment-types'; static const supported = '/supported'; - static const defaultsAll = '/defaults/all'; static const List _notSupportedCrypto = []; static const List _notSupportedFiat = []; static Map _onrampMetadata = {}; - final ThemeStore _themeStore; - - String? recommendedPaymentType; + final SettingsStore _settingsStore; String get _apiKey => secrets.onramperApiKey; @@ -60,36 +57,6 @@ class OnRamperBuyProvider extends BuyProvider { @override bool get isAggregator => true; - Future getRecommendedPaymentType(bool isBuyAction) async { - - final params = {'type': isBuyAction ? 'buy' : 'sell'}; - - final url = Uri.https(_baseApiUrl, '$supported$defaultsAll', params); - - try { - final response = await ProxyWrapper().get( - clearnetUri: url, - headers: {'Authorization': _apiKey, 'accept': 'application/json'}, - ); - - if (response.statusCode == 200) { - final Map data = jsonDecode(response.body) as Map; - final recommended = data['message']['recommended'] as Map; - - final recommendedPaymentType = recommended['paymentMethod'] as String?; - - return recommendedPaymentType ; - } else { - final responseBody = - jsonDecode(response.body) as Map; - printV('Failed to fetch available payment types: ${responseBody['message']}'); - } - } catch (e) { - printV('Failed to fetch available payment types: $e'); - } - return null; - } - Future> getAvailablePaymentTypes( String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async { @@ -105,19 +72,14 @@ class OnRamperBuyProvider extends BuyProvider { try { final response = - await ProxyWrapper().get(clearnetUri: url, headers: {'Authorization': _apiKey, 'accept': 'application/json'}); - + await http.get(url, headers: {'Authorization': _apiKey, 'accept': 'application/json'}); + if (response.statusCode == 200) { final Map data = jsonDecode(response.body) as Map; final List message = data['message'] as List; - - final allAvailablePaymentMethods = message + return message .map((item) => PaymentMethod.fromOnramperJson(item as Map)) .toList(); - - recommendedPaymentType = await getRecommendedPaymentType(isBuyAction); - - return allAvailablePaymentMethods; } else { final responseBody = jsonDecode(response.body) as Map; @@ -135,8 +97,7 @@ class OnRamperBuyProvider extends BuyProvider { try { final response = - await ProxyWrapper().get(clearnetUri: url, headers: {'Authorization': _apiKey, 'accept': 'application/json'}); - + await http.get(url, headers: {'Authorization': _apiKey, 'accept': 'application/json'}); if (response.statusCode == 200) { final Map data = jsonDecode(response.body) as Map; @@ -170,13 +131,13 @@ class OnRamperBuyProvider extends BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode}) async { String? paymentMethod; - if (paymentType == PaymentType.all && recommendedPaymentType != null) paymentMethod = recommendedPaymentType!; - else if (paymentType == PaymentType.unknown) paymentMethod = customPaymentMethodType; - else if (paymentType != null) paymentMethod = normalizePaymentMethod(paymentType); + if (paymentType != null && paymentType != PaymentType.all) { + paymentMethod = normalizePaymentMethod(paymentType); + if (paymentMethod == null) paymentMethod = paymentType.name; + } final actionType = isBuyAction ? 'buy' : 'sell'; @@ -199,8 +160,8 @@ class OnRamperBuyProvider extends BuyProvider { final headers = {'Authorization': _apiKey, 'accept': 'application/json'}; try { - final response = await ProxyWrapper().get(clearnetUri: url, headers: headers); - + final response = await http.get(url, headers: headers); + if (response.statusCode == 200) { final data = jsonDecode(response.body) as List; if (data.isEmpty) return null; @@ -221,7 +182,7 @@ class OnRamperBuyProvider extends BuyProvider { if (rampMetaData == null) continue; final quote = Quote.fromOnramperJson( - item, isBuyAction, _onrampMetadata, _getPaymentTypeByString(paymentMethod), customPaymentMethodType); + item, isBuyAction, _onrampMetadata, _getPaymentTypeByString(paymentMethod)); quote.setFiatCurrency = fiatCurrency; quote.setCryptoCurrency = cryptoCurrency; validQuotes.add(quote); @@ -249,18 +210,22 @@ class OnRamperBuyProvider extends BuyProvider { String? countryCode}) async { final actionType = isBuyAction ? 'buy' : 'sell'; - final primaryColor = getColorStr(Theme.of(context).colorScheme.primary,); - final secondaryColor = getColorStr(Theme.of(context).colorScheme.surface); - final primaryTextColor = getColorStr(Theme.of(context).colorScheme.onSurface); + final primaryColor = getColorStr(Theme.of(context).primaryColor); + final secondaryColor = getColorStr(Theme.of(context).colorScheme.background); + final primaryTextColor = getColorStr(Theme.of(context).extension()!.titleColor); final secondaryTextColor = - getColorStr(Theme.of(context).colorScheme.onSurfaceVariant); - final containerColor = getColorStr(Theme.of(context).colorScheme.surface); - var cardColor = getColorStr(Theme.of(context).colorScheme.surfaceContainer); + getColorStr(Theme.of(context).extension()!.secondaryTextColor); + final containerColor = getColorStr(Theme.of(context).colorScheme.background); + var cardColor = getColorStr(Theme.of(context).cardColor); + + if (_settingsStore.currentTheme.title == S.current.high_contrast_theme) { + cardColor = getColorStr(Colors.white); + } final defaultCrypto = quote.cryptoCurrency.title + _getNormalizeNetwork(quote.cryptoCurrency).toLowerCase(); - final paymentMethod = quote.paymentType == PaymentType.unknown ? quote.customPaymentMethodType : normalizePaymentMethod(quote.paymentType); + final paymentMethod = normalizePaymentMethod(quote.paymentType); final uri = Uri.https(_baseUrl, '', { 'apiKey': _apiKey, @@ -365,8 +330,6 @@ class OnRamperBuyProvider extends BuyProvider { return 'dana'; case PaymentType.ideal: return 'ideal'; - case PaymentType.pixPay: - return 'pix'; default: return null; } @@ -416,10 +379,8 @@ class OnRamperBuyProvider extends BuyProvider { return PaymentType.dana; case 'ideal': return PaymentType.ideal; - case 'pix': - return PaymentType.pixPay; default: - return PaymentType.unknown; + return PaymentType.all; } } diff --git a/lib/buy/payment_method.dart b/lib/buy/payment_method.dart index 322ca68ba..14b119aa0 100644 --- a/lib/buy/payment_method.dart +++ b/lib/buy/payment_method.dart @@ -34,8 +34,6 @@ enum PaymentType { yellowCardBankTransfer, fiatBalance, bancontact, - pixPay, - unknown, } extension PaymentTypeTitle on PaymentType { @@ -103,8 +101,6 @@ extension PaymentTypeTitle on PaymentType { return 'Fiat Balance'; case PaymentType.bancontact: return 'Bancontact'; - case PaymentType.pixPay: - return 'PIX Pay'; default: return null; } @@ -162,14 +158,12 @@ class PaymentMethod extends SelectableOption { required this.customTitle, required this.customIconPath, this.customDescription, - this.customPaymentMethodType, }) : super(title: paymentMethodType.title ?? customTitle); final PaymentType paymentMethodType; final String customTitle; final String customIconPath; final String? customDescription; - final String? customPaymentMethodType; bool isSelected = false; @override @@ -194,8 +188,7 @@ class PaymentMethod extends SelectableOption { factory PaymentMethod.fromOnramperJson(Map json) { final type = PaymentMethod.getPaymentTypeId(json['paymentTypeId'] as String?); return PaymentMethod( - paymentMethodType: type ?? PaymentType.unknown, - customPaymentMethodType: json['paymentTypeId'] as String?, + paymentMethodType: type, customTitle: json['name'] as String? ?? 'Unknown', customIconPath: json['icon'] as String? ?? 'assets/images/card.png', customDescription: json['description'] as String?); @@ -219,7 +212,7 @@ class PaymentMethod extends SelectableOption { final type = PaymentMethod.getPaymentTypeId(json['paymentMethod'] as String?); final logos = json['logos'] as Map; return PaymentMethod( - paymentMethodType: type ?? PaymentType.unknown, + paymentMethodType: type, customTitle: json['name'] as String? ?? 'Unknown', customIconPath: logos['dark'] as String? ?? 'assets/images/card.png', customDescription: json['description'] as String?); @@ -228,13 +221,13 @@ class PaymentMethod extends SelectableOption { factory PaymentMethod.fromKryptonimJson(Map json) { final type = PaymentMethod.getPaymentTypeId(json['payment_method'] as String?); return PaymentMethod( - paymentMethodType: type ?? PaymentType.unknown, + paymentMethodType: type, customTitle: json['payment_method'] as String? ?? 'Unknown', customIconPath: 'assets/images/card.png', ); } - static PaymentType? getPaymentTypeId(String? type) { + static PaymentType getPaymentTypeId(String? type) { switch (type?.toLowerCase()) { case 'banktransfer': case 'bank': @@ -296,10 +289,8 @@ class PaymentMethod extends SelectableOption { return PaymentType.sepaOpenBankingPayment; case 'bancontact': return PaymentType.bancontact; - case 'pix': - return PaymentType.pixPay; default: - return null; + return PaymentType.all; } } } diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index 4b9c1aa70..93efd5642 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -11,7 +11,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -19,6 +18,7 @@ import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class RobinhoodBuyProvider extends BuyProvider { @@ -69,8 +69,7 @@ class RobinhoodBuyProvider extends BuyProvider { final uri = Uri.https(_apiBaseUrl, '$_assetsPath', {'applicationId': _applicationId}); try { - final response = await ProxyWrapper().get(clearnetUri: uri, headers: {'accept': 'application/json'}); - + final response = await http.get(uri, headers: {'accept': 'application/json'}); if (response.statusCode == 200) { final responseData = jsonDecode(response.body) as Map; @@ -123,14 +122,12 @@ class RobinhoodBuyProvider extends BuyProvider { final uri = Uri.https(_cIdBaseUrl, "/api/robinhood"); - var response = await ProxyWrapper().post( - clearnetUri: uri, - headers: {'Content-Type': 'application/json'}, - body: json.encode({'valid_until': valid_until, 'wallet': walletAddress, 'signature': signature}), - ); + var response = await http.post(uri, + headers: {'Content-Type': 'application/json'}, + body: json + .encode({'valid_until': valid_until, 'wallet': walletAddress, 'signature': signature})); if (response.statusCode == 200) { - return (jsonDecode(response.body) as Map)['connectId'] as String; } else { throw Exception('Provider currently unavailable. Status: ${response.statusCode}'); @@ -195,7 +192,6 @@ class RobinhoodBuyProvider extends BuyProvider { required bool isBuyAction, required String walletAddress, PaymentType? paymentType, - String? customPaymentMethodType, String? countryCode}) async { String? paymentMethod; @@ -222,8 +218,7 @@ class RobinhoodBuyProvider extends BuyProvider { Uri.https('api.robinhood.com', '/catpay/v1/${cryptoCurrency.title}/quote/', queryParams); try { - final response = await ProxyWrapper().get(clearnetUri: uri, headers: {'accept': 'application/json'}); - + final response = await http.get(uri, headers: {'accept': 'application/json'}); final responseData = jsonDecode(response.body) as Map; if (response.statusCode == 200) { @@ -272,7 +267,7 @@ class RobinhoodBuyProvider extends BuyProvider { case 'bank_transfer': return PaymentType.bankTransfer; default: - return PaymentType.unknown; + return PaymentType.all; } } } diff --git a/lib/buy/wyre/wyre_buy_provider.dart b/lib/buy/wyre/wyre_buy_provider.dart index 3f9844df6..7fe6f4be3 100644 --- a/lib/buy/wyre/wyre_buy_provider.dart +++ b/lib/buy/wyre/wyre_buy_provider.dart @@ -3,7 +3,7 @@ import 'package:cake_wallet/buy/buy_exception.dart'; import 'package:cake_wallet/buy/pairs_utils.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart'; import 'package:cake_wallet/buy/buy_amount.dart'; import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/buy/buy_provider_description.dart'; @@ -73,21 +73,18 @@ class WyreBuyProvider extends BuyProvider { 'referrerAccountId': _accountId, 'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest'] }; - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: { - 'Authorization': 'Bearer $_secretKey', - 'Content-Type': 'application/json', - 'cache-control': 'no-cache' - }, - body: json.encode(body), - ); + final response = await post(uri, + headers: { + 'Authorization': 'Bearer $_secretKey', + 'Content-Type': 'application/json', + 'cache-control': 'no-cache' + }, + body: json.encode(body)); if (response.statusCode != 200) { throw BuyException(title: providerDescription, content: 'Url $url is not found!'); } - final responseJSON = json.decode(response.body) as Map; final urlFromResponse = responseJSON['url'] as String; return urlFromResponse; @@ -104,21 +101,18 @@ class WyreBuyProvider extends BuyProvider { 'country': _countryCode }; final uri = Uri.parse(quoteUrl); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: { - 'Authorization': 'Bearer $_secretKey', - 'Content-Type': 'application/json', - 'cache-control': 'no-cache' - }, - body: json.encode(body), - ); + final response = await post(uri, + headers: { + 'Authorization': 'Bearer $_secretKey', + 'Content-Type': 'application/json', + 'cache-control': 'no-cache' + }, + body: json.encode(body)); if (response.statusCode != 200) { throw BuyException(title: providerDescription, content: 'Quote is not found!'); } - final responseJSON = json.decode(response.body) as Map; final sourceAmount = responseJSON['sourceAmount'] as double; final destAmount = responseJSON['destAmount'] as double; @@ -131,7 +125,8 @@ class WyreBuyProvider extends BuyProvider { Future findOrderById(String id) async { final orderUrl = baseApiUrl + _ordersSuffix + '/$id'; final orderUri = Uri.parse(orderUrl); - final orderResponse = await ProxyWrapper().get(clearnetUri: orderUri); + final orderResponse = await get(orderUri); + if (orderResponse.statusCode != 200) { throw BuyException(title: providerDescription, content: 'Order $id is not found!'); } @@ -147,7 +142,8 @@ class WyreBuyProvider extends BuyProvider { final transferUrl = baseApiUrl + _transferSuffix + transferId + _trackSuffix; final transferUri = Uri.parse(transferUrl); - final transferResponse = await ProxyWrapper().get(clearnetUri: transferUri); + final transferResponse = await get(transferUri); + if (transferResponse.statusCode != 200) { throw BuyException(title: providerDescription, content: 'Transfer $transferId is not found!'); } diff --git a/lib/cake_pay/cake_pay_api.dart b/lib/cake_pay/cake_pay_api.dart index a3c7f48d0..5f1a350c0 100644 --- a/lib/cake_pay/cake_pay_api.dart +++ b/lib/cake_pay/cake_pay_api.dart @@ -3,9 +3,9 @@ import 'dart:convert'; import 'package:cake_wallet/cake_pay/cake_pay_order.dart'; import 'package:cake_wallet/cake_pay/cake_pay_user_credentials.dart'; import 'package:cake_wallet/cake_pay/cake_pay_vendor.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cake_wallet/entities/country.dart'; +import 'package:http/http.dart' as http; class CakePayApi { static const testBaseUri = false; @@ -32,17 +32,12 @@ class CakePayApi { 'Content-Type': 'application/json', 'Authorization': 'Api-Key $apiKey', }; - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode({'email': email}), - ); + final response = await http.post(uri, headers: headers, body: json.encode({'email': email})); if (response.statusCode != 200) { throw Exception('Unexpected http status: ${response.statusCode}'); } - final bodyJson = json.decode(response.body) as Map; if (bodyJson.containsKey('user') && bodyJson['user']['email'] != null) { @@ -69,17 +64,12 @@ class CakePayApi { }; final query = {'email': email, 'otp': code}; - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(query), - ); + final response = await http.post(uri, headers: headers, body: json.encode(query)); if (response.statusCode != 200) { throw Exception('Unexpected http status: ${response.statusCode}'); } - final bodyJson = json.decode(response.body) as Map; if (bodyJson.containsKey('error')) { @@ -126,14 +116,9 @@ class CakePayApi { }; try { - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(query), - ); + final response = await http.post(uri, headers: headers, body: json.encode(query)); if (response.statusCode != 201) { - final responseBody = json.decode(response.body); if (responseBody is List) { throw '${responseBody[0]}'; @@ -142,7 +127,6 @@ class CakePayApi { } } - final bodyJson = json.decode(response.body) as Map; return CakePayOrder.fromMap(bodyJson); } catch (e) { @@ -161,8 +145,7 @@ class CakePayApi { 'X-CSRFToken': CSRFToken, }; - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); - + final response = await http.get(uri, headers: headers); printV('Response: ${response.statusCode}'); @@ -185,11 +168,7 @@ class CakePayApi { }; try { - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode({'email': email}), - ); + final response = await http.post(uri, headers: headers, body: json.encode({'email': email})); if (response.statusCode != 200) { throw Exception('Unexpected http status: ${response.statusCode}'); @@ -208,8 +187,8 @@ class CakePayApi { 'Authorization': 'Api-Key $apiKey', }; - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); - + final response = await http.get(uri, headers: headers); + if (response.statusCode != 200) { throw Exception('Unexpected http status: ${response.statusCode}'); } @@ -255,15 +234,14 @@ class CakePayApi { 'Authorization': 'Api-Key $apiKey', }; - var response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); - + var response = await http.get(uri, headers: headers); if (response.statusCode != 200) { throw Exception( 'Failed to fetch vendors: statusCode - ${response.statusCode}, queryParams -$queryParams, response - ${response.body}'); } - final bodyJson = json.decode(response.body); + final bodyJson = json.decode(utf8.decode(response.bodyBytes)); if (bodyJson is List && bodyJson.isEmpty) { return []; diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index c79ac0980..911e939d1 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -38,9 +38,9 @@ class AddressValidator extends TextValidator { '|[0-9a-zA-Z]{105}|addr1[0-9a-zA-Z]{98}'; case CryptoCurrency.btc: pattern = - '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}'; + '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${RegExp(r'(bc|tb)1q[ac-hj-np-z02-9]{25,39}}').pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}'; case CryptoCurrency.ltc: - pattern = '${P2wpkhAddress.regex.pattern}|${MwebAddress.regex.pattern}'; + pattern = '^${RegExp(r'ltc1q[ac-hj-np-z02-9]{25,39}').pattern}\$|^${MwebAddress.regex.pattern}\$'; case CryptoCurrency.nano: pattern = '[0-9a-zA-Z_]+'; case CryptoCurrency.banano: @@ -335,6 +335,10 @@ class AddressValidator extends TextValidator { } } - return pattern != null ? "($pattern)" : null; + if (pattern != null) { + return "$BEFORE_REGEX($pattern)$AFTER_REGEX"; + } + + return null; } } diff --git a/lib/core/background_sync.dart b/lib/core/background_sync.dart index a503f5c1b..12eb81f99 100644 --- a/lib/core/background_sync.dart +++ b/lib/core/background_sync.dart @@ -7,7 +7,6 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; -import 'package:cake_wallet/utils/tor.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; import 'package:cw_core/sync_status.dart'; @@ -16,7 +15,6 @@ import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter/foundation.dart'; class BackgroundSync { final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); @@ -92,11 +90,6 @@ class BackgroundSync { } Future sync() async { - final settingsStore = getIt.get(); - if (settingsStore.currentBuiltinTor) { - printV("Starting Tor"); - await ensureTorStarted(context: null); - } printV("Background sync started"); await _syncWallets(); printV("Background sync completed"); @@ -107,6 +100,7 @@ class BackgroundSync { final walletListViewModel = getIt.get(); final settingsStore = getIt.get(); + final List moneroWallets = walletListViewModel.wallets .where((element) => !element.isHardware) .where((element) => ![WalletType.haven, WalletType.decred].contains(element.type)) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 87bb71ce9..cb36072fe 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/get_encryption_key.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; -import 'package:cake_wallet/themes/utils/theme_list.dart'; +import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cw_core/root_dir.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/utils/print_verbose.dart'; @@ -83,7 +83,7 @@ class $BackupService { outer: for (var file in zip.files) { final filename = file.name; - for (var ignore in ignoreFiles) { + for (var ignore in ignoreFiles) { if (filename.endsWith(ignore) && !filename.contains("wallets/")) { printV("ignoring backup file: $filename"); continue outer; @@ -110,7 +110,7 @@ class $BackupService { } Future verifyWallets() async { - final walletInfoSource = await reloadHiveWalletInfoBox(); + final walletInfoSource = await _reloadHiveWalletInfoBox(); correctWallets = walletInfoSource.values.where((info) => availableWalletTypes.contains(info.type)).toList(); @@ -119,7 +119,7 @@ class $BackupService { } } - Future> reloadHiveWalletInfoBox() async { + Future> _reloadHiveWalletInfoBox() async { final appDir = await getAppDir(); await CakeHive.close(); CakeHive.init(appDir.path); @@ -145,7 +145,7 @@ class $BackupService { MapEntry(key, TransactionDescription.fromJson(value as Map))); var box = transactionDescriptionBox; if (!box.isOpen) { - final transactionDescriptionsBoxKey = + final transactionDescriptionsBoxKey = await getEncryptionKey(secureStorage: _secureStorage, forKey: TransactionDescription.boxKey); box = await CakeHive.openBox( TransactionDescription.boxName, @@ -251,22 +251,19 @@ class $BackupService { await importWalletKeychainInfo(info); }); - if (keychainJSON['_all'] is Map) { - for (var key in (keychainJSON['_all'] as Map).keys) { - try { - if (!key.startsWith('MONERO_WALLET_')) continue; - final decodedPassword = decodeWalletPassword( - password: keychainJSON['_all'][key].toString()); - final walletName = key.split('_WALLET_')[1]; - final walletType = key.split('_WALLET_')[0].toLowerCase(); - await importWalletKeychainInfo({ - 'name': walletName, - 'type': "WalletType.$walletType", - 'password': decodedPassword, - }); - } catch (e) { - printV('Error importing wallet ($key) password: $e'); - } + for (var key in (keychainJSON['_all'] as Map).keys) { + try { + if (!key.startsWith('MONERO_WALLET_')) continue; + final decodedPassword = decodeWalletPassword(password: keychainJSON['_all'][key].toString()); + final walletName = key.split('_WALLET_')[1]; + final walletType = key.split('_WALLET_')[0].toLowerCase(); + await importWalletKeychainInfo({ + 'name': walletName, + 'type': "WalletType.$walletType", + 'password': decodedPassword, + }); + } catch (e) { + printV('Error importing wallet ($key) password: $e'); } } @@ -288,15 +285,13 @@ class $BackupService { return { 'name': walletInfo.name, 'type': walletInfo.type.toString(), - 'password': await keyService.getWalletPassword(walletName: walletInfo.name), - 'hardwareWalletType': walletInfo.hardwareWalletType?.index, + 'password': await keyService.getWalletPassword(walletName: walletInfo.name) }; } catch (e) { return { 'name': walletInfo.name, 'type': walletInfo.type.toString(), - 'password': '', - 'hardwareWalletType': walletInfo.hardwareWalletType?.index, + 'password': '' }; } })); diff --git a/lib/core/backup_service_v3.dart b/lib/core/backup_service_v3.dart index a0640dfd3..76798aa64 100644 --- a/lib/core/backup_service_v3.dart +++ b/lib/core/backup_service_v3.dart @@ -10,7 +10,6 @@ import 'package:cake_wallet/utils/package_info.dart'; import 'package:crypto/crypto.dart'; import 'package:cw_core/root_dir.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/wallet_info.dart'; import 'package:flutter/foundation.dart'; enum BackupVersion { @@ -178,7 +177,7 @@ class BackupServiceV3 extends $BackupService { final archive = ZipDecoder().decodeStream(inputStream); final metadataFile = archive.findFile('metadata.json'); if (metadataFile == null) { - return BackupVersion.unknown; + throw Exception('Invalid v3 backup: missing metadata.json'); } final metadataBytes = metadataFile.rawContent!.readBytes(); final metadataString = utf8.decode(metadataBytes); @@ -189,7 +188,7 @@ class BackupServiceV3 extends $BackupService { } } - return BackupVersion.unknown; + throw Exception('Invalid backup file: unknown version'); } finally { raf.closeSync(); } @@ -306,7 +305,6 @@ class BackupServiceV3 extends $BackupService { // Continue importing the backup the old way await super.verifyWallets(); - await verifyHardwareWallets(password); await super.importKeychainDumpV2(password); await super.importPreferencesDump(); await super.importTransactionDescriptionDump(); @@ -315,39 +313,6 @@ class BackupServiceV3 extends $BackupService { decryptedData.deleteSync(); } - Future verifyHardwareWallets(String password, - {String keychainSalt = secrets.backupKeychainSalt}) async { - final walletInfoSource = await reloadHiveWalletInfoBox(); - final appDir = await getAppDir(); - final keychainDumpFile = File('${appDir.path}/~_keychain_dump'); - final decryptedKeychainDumpFileData = await decryptV2( - keychainDumpFile.readAsBytesSync(), '$keychainSalt$password'); - final keychainJSON = json.decode(utf8.decode(decryptedKeychainDumpFileData)) - as Map; - final keychainWalletsInfo = keychainJSON['wallets'] as List; - - final expectedHardwareWallets = keychainWalletsInfo - .where((e) => - (e as Map).containsKey("hardwareWalletType") && - e["hardwareWalletType"] != null) - .toList(); - - for (final expectedHardwareWallet in expectedHardwareWallets) { - final info = expectedHardwareWallet as Map; - final actualWalletInfo = walletInfoSource.values - .where((e) => - e.name == info['name'] && e.type.toString() == info['type']) - .firstOrNull; - if (actualWalletInfo != null && - info["hardwareWalletType"] != - actualWalletInfo.hardwareWalletType?.index) { - actualWalletInfo.hardwareWalletType = - HardwareWalletType.values[info["hardwareWalletType"] as int]; - await actualWalletInfo.save(); - } - } - } - Future exportBackupFileV3(String password, {String nonce = secrets.backupSalt}) async { final metadata = BackupMetadata( version: BackupVersion.v3, @@ -502,4 +467,4 @@ This backup was created on ${DateTime.now().toIso8601String()} file.writeAsBytesSync(data); return file; } -} +} \ No newline at end of file diff --git a/lib/core/fiat_conversion_service.dart b/lib/core/fiat_conversion_service.dart index 669e38128..8a37175b4 100644 --- a/lib/core/fiat_conversion_service.dart +++ b/lib/core/fiat_conversion_service.dart @@ -1,35 +1,37 @@ -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'dart:convert'; +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; const _fiatApiClearNetAuthority = 'fiat-api.cakewallet.com'; -const _fiatApiOnionAuthority = 'kfkyguqtz5vcnbvar5pjgddkaeawbo4j3r4fj3e22k3tzqageplosiid.onion'; +const _fiatApiOnionAuthority = 'n4z7bdcmwk2oyddxvzaap3x2peqcplh3pzdy7tpkk5ejz5n4mhfvoxqd.onion'; const _fiatApiPath = '/v2/rates'; -Future _fetchPrice(String crypto, String fiat, bool torOnly) async { +Future _fetchPrice(Map args) async { + final crypto = args['crypto'] as String; + final fiat = args['fiat'] as String; + final torOnly = args['torOnly'] as bool; final Map queryParams = { 'interval_count': '1', 'base': crypto.split(".").first, 'quote': fiat, + 'key': secrets.fiatApiKey, }; num price = 0.0; try { - final onionUri = Uri.http(_fiatApiOnionAuthority, _fiatApiPath, queryParams); - final clearnetUri = Uri.https(_fiatApiClearNetAuthority, _fiatApiPath, queryParams); + late final Uri uri; + if (torOnly) { + uri = Uri.http(_fiatApiOnionAuthority, _fiatApiPath, queryParams); + } else { + uri = Uri.https(_fiatApiClearNetAuthority, _fiatApiPath, queryParams); + } - final response = await ProxyWrapper().get( - onionUri: onionUri, - clearnetUri: torOnly ? onionUri : clearnetUri, - headers: { - "x-api-key": secrets.fiatApiKey, - } - ); - + final response = await get(uri); if (response.statusCode != 200) { return 0.0; @@ -48,11 +50,18 @@ Future _fetchPrice(String crypto, String fiat, bool torOnly) async { } } +Future _fetchPriceAsync(CryptoCurrency crypto, FiatCurrency fiat, bool torOnly) async => + compute(_fetchPrice, { + 'fiat': fiat.toString(), + 'crypto': crypto.toString(), + 'torOnly': torOnly, + }); + class FiatConversionService { static Future fetchPrice({ required CryptoCurrency crypto, required FiatCurrency fiat, required bool torOnly, }) async => - await _fetchPrice(crypto.toString(), fiat.toString(), torOnly); + await _fetchPriceAsync(crypto, fiat, torOnly); } diff --git a/lib/core/open_crypto_pay/open_cryptopay_service.dart b/lib/core/open_crypto_pay/open_cryptopay_service.dart index 4b317d9c3..6449bbf90 100644 --- a/lib/core/open_crypto_pay/open_cryptopay_service.dart +++ b/lib/core/open_crypto_pay/open_cryptopay_service.dart @@ -5,13 +5,15 @@ import 'package:cake_wallet/core/open_crypto_pay/exceptions.dart'; import 'package:cake_wallet/core/open_crypto_pay/lnurl.dart'; import 'package:cake_wallet/core/open_crypto_pay/models.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart'; class OpenCryptoPayService { static bool isOpenCryptoPayQR(String value) => value.toLowerCase().contains("lightning=lnurl") || value.toLowerCase().startsWith("lnurl"); + final Client _httpClient = Client(); + Future commitOpenCryptoPayRequest( String txHex, { required String txId, @@ -29,8 +31,7 @@ class OpenCryptoPayService { queryParams['tx'] = txId; final response = - await ProxyWrapper().get(clearnetUri: Uri.https(uri.authority, uri.path, queryParams)); - + await _httpClient.get(Uri.https(uri.authority, uri.path, queryParams)); if (response.statusCode == 200) { final body = jsonDecode(response.body) as Map; @@ -39,13 +40,13 @@ class OpenCryptoPayService { throw OpenCryptoPayException(body.toString()); } throw OpenCryptoPayException( - "Unexpected status code ${response.statusCode} ${response}"); + "Unexpected status code ${response.statusCode} ${response.body}"); } Future cancelOpenCryptoPayRequest(OpenCryptoPayRequest request) async { final uri = Uri.parse(request.callbackUrl.replaceAll("/cb/", "/cancel/")); - await ProxyWrapper().delete(clearnetUri: uri); + await _httpClient.delete(uri); } Future getOpenCryptoPayInvoice(String lnUrl) async { @@ -72,8 +73,7 @@ class OpenCryptoPayService { Future<(_OpenCryptoPayQuote, Map>)> _getOpenCryptoPayParams(Uri uri) async { - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await _httpClient.get(uri); if (response.statusCode == 200) { final responseBody = jsonDecode(response.body) as Map; @@ -119,8 +119,8 @@ class OpenCryptoPayService { queryParams['asset'] = asset.title; queryParams['method'] = _getMethod(asset); - final response = await ProxyWrapper().get(clearnetUri: Uri.https(uri.authority, uri.path, queryParams)); - + final response = + await _httpClient.get(Uri.https(uri.authority, uri.path, queryParams)); if (response.statusCode == 200) { final responseBody = jsonDecode(response.body) as Map; diff --git a/lib/core/trade_monitor.dart b/lib/core/trade_monitor.dart deleted file mode 100644 index 3b696b88a..000000000 --- a/lib/core/trade_monitor.dart +++ /dev/null @@ -1,247 +0,0 @@ -import 'dart:async'; -import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/store/dashboard/trades_store.dart'; -import 'package:cake_wallet/entities/exchange_api_mode.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/letsexchange_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/swaptrade_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; -import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:hive/hive.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class TradeMonitor { - static const int _tradeCheckIntervalMinutes = 5; - static const int _maxTradeAgeHours = 24; - - TradeMonitor({ - required this.tradesStore, - required this.trades, - required this.appStore, - required this.preferences, - }); - - final TradesStore tradesStore; - final Box trades; - final AppStore appStore; - final Map _tradeTimers = {}; - final SharedPreferences preferences; - - ExchangeProvider? _getProviderByDescription(ExchangeProviderDescription description) { - switch (description) { - case ExchangeProviderDescription.changeNow: - return ChangeNowExchangeProvider(settingsStore: appStore.settingsStore); - case ExchangeProviderDescription.sideShift: - return SideShiftExchangeProvider(); - case ExchangeProviderDescription.simpleSwap: - return SimpleSwapExchangeProvider(); - case ExchangeProviderDescription.trocador: - return TrocadorExchangeProvider(); - case ExchangeProviderDescription.exolix: - return ExolixExchangeProvider(); - case ExchangeProviderDescription.thorChain: - return ThorChainExchangeProvider(tradesStore: trades); - case ExchangeProviderDescription.swapTrade: - return SwapTradeExchangeProvider(); - case ExchangeProviderDescription.letsExchange: - return LetsExchangeExchangeProvider(); - case ExchangeProviderDescription.stealthEx: - return StealthExExchangeProvider(); - case ExchangeProviderDescription.chainflip: - return ChainflipExchangeProvider(tradesStore: trades); - case ExchangeProviderDescription.xoSwap: - return XOSwapExchangeProvider(); - } - return null; - } - - void monitorActiveTrades(String walletId) { - // Checks if the trade monitoring is permitted - // i.e the user has not disabled the exchange api mode or the status updates - final isTradeMonitoringPermitted = _isTradeMonitoringPermitted(); - if (!isTradeMonitoringPermitted) { - return; - } - - final trades = tradesStore.trades; - final tradesToCancel = []; - - for (final item in trades) { - final trade = item.trade; - - final provider = _getProviderByDescription(trade.provider); - - // Multiple checks to see if to skip the trade, if yes, we cancel the timer if it exists - if (_shouldSkipTrade(trade, walletId, provider)) { - tradesToCancel.add(trade.id); - continue; - } - - if (_tradeTimers.containsKey(trade.id)) { - printV('Trade ${trade.id} is already being monitored'); - continue; - } else { - _startTradeMonitoring(trade, provider!); - } - } - - // After going through the list of available trades, we cancel the timers in the tradesToCancel list - _cancelMultipleTradeTimers(tradesToCancel); - } - - bool _isTradeMonitoringPermitted() { - final disableAutomaticExchangeStatusUpdates = - appStore.settingsStore.disableAutomaticExchangeStatusUpdates; - if (disableAutomaticExchangeStatusUpdates) { - printV('Automatic exchange status updates are disabled'); - return false; - } - - final exchangeApiMode = appStore.settingsStore.exchangeStatus; - if (exchangeApiMode == ExchangeApiMode.disabled) { - printV('Exchange API mode is disabled'); - return false; - } - - return true; - } - - bool _shouldSkipTrade(Trade trade, String walletId, ExchangeProvider? provider) { - if (trade.walletId != walletId) { - printV('Skipping trade ${trade.id} because it\'s not for this wallet'); - return true; - } - - final createdAt = trade.createdAt; - if (createdAt == null) { - printV('Skipping trade ${trade.id} because it has no createdAt'); - return true; - } - - if (DateTime.now().difference(createdAt).inHours > _maxTradeAgeHours) { - printV('Skipping trade ${trade.id} because it\'s older than ${_maxTradeAgeHours} hours'); - return true; - } - - if (_isFinalState(trade.state)) { - printV('Skipping trade ${trade.id} because it\'s in a final state'); - return true; - } - - if (provider == null) { - printV('Skipping trade ${trade.id} because the provider is not supported'); - return true; - } - - if (appStore.settingsStore.exchangeStatus == ExchangeApiMode.torOnly && - !provider.supportsOnionAddress) { - printV('Skipping ${provider.description}, no TOR support'); - return true; - } - - return false; - } - - void _startTradeMonitoring(Trade trade, ExchangeProvider provider) { - final timer = Timer.periodic( - Duration(minutes: _tradeCheckIntervalMinutes), - (_) => _checkTradeStatus(trade, provider), - ); - - _checkTradeStatus(trade, provider); - - _tradeTimers[trade.id] = timer; - } - - Future _checkTradeStatus(Trade trade, ExchangeProvider provider) async { - final lastUpdatedAtFromPrefs = preferences.getString('trade_${trade.id}_updated_at'); - - if (lastUpdatedAtFromPrefs != null) { - final lastUpdatedAtDateTime = DateTime.parse(lastUpdatedAtFromPrefs); - final timeSinceLastUpdate = DateTime.now().difference(lastUpdatedAtDateTime).inMinutes; - - if (timeSinceLastUpdate < _tradeCheckIntervalMinutes) { - printV( - 'Skipping trade ${trade.id} status update check because it was updated less than ${_tradeCheckIntervalMinutes} minutes ago ($timeSinceLastUpdate minutes ago)', - ); - return; - } - } - - try { - final updated = await provider.findTradeById(id: trade.id); - trade - ..stateRaw = updated.state.raw - ..receiveAmount = updated.receiveAmount ?? trade.receiveAmount - ..outputTransaction = updated.outputTransaction ?? trade.outputTransaction; - printV('Trade ${trade.id} updated: ${trade.state}'); - await trade.save(); - - await preferences.setString('trade_${trade.id}_updated_at', DateTime.now().toIso8601String()); - printV('Trade ${trade.id} updated at: ${DateTime.now().toIso8601String()}'); - - // If the updated trade is in a final state, we cancel the timer - if (_isFinalState(updated.state)) { - printV('Trade ${trade.id} is in final state'); - _cancelSingleTradeTimer(trade.id); - } - } catch (e) { - printV('Error fetching status for ${trade.id}: $e'); - } - } - - bool _isFinalState(TradeState state) { - return { - TradeState.completed.raw, - TradeState.success.raw, - TradeState.confirmed.raw, - TradeState.settled.raw, - TradeState.finished.raw, - TradeState.expired.raw, - TradeState.failed.raw, - TradeState.notFound.raw, - }.contains(state.raw); - } - - void _cancelSingleTradeTimer(String tradeId) { - if (_tradeTimers.containsKey(tradeId)) { - _tradeTimers[tradeId]?.cancel(); - _tradeTimers.remove(tradeId); - printV('Trade timer for ${tradeId} cancelled'); - } - } - - void _cancelMultipleTradeTimers(List tradeIds) { - for (final tradeId in tradeIds) { - _cancelSingleTradeTimer(tradeId); - } - } - - /// This is called when the app is brought back to foreground. - void resumeTradeMonitoring() { - if (appStore.wallet != null) { - monitorActiveTrades(appStore.wallet!.id); - } - } - - /// There's no need to run the trade checks when the app is in background. - /// We only want to update the trade status when the app is in foreground. - /// This helps to reduce the battery usage, network usage and enhance overall privacy. - /// - /// This is called when the app is sent to background or when the app is closed. - void stopTradeMonitoring() { - printV('Stopping trade monitoring'); - _cancelMultipleTradeTimers(_tradeTimers.keys.toList()); - } -} diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart index f16bf7e14..382b1d6c2 100644 --- a/lib/core/wallet_loading_service.dart +++ b/lib/core/wallet_loading_service.dart @@ -73,11 +73,8 @@ class WalletLoadingService { return wallet; } catch (error, stack) { await ExceptionHandler.resetLastPopupDate(); - final isLedgerError = await ExceptionHandler.isLedgerError(error); - if (isLedgerError) rethrow; await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack)); - // try fetching the seeds of the corrupted wallet to show it to the user String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):"; try { diff --git a/lib/core/yat_service.dart b/lib/core/yat_service.dart index 84aac1626..92e81e5ef 100644 --- a/lib/core/yat_service.dart +++ b/lib/core/yat_service.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:cake_wallet/entities/yat_record.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart'; class YatService { static bool isDevMode = false; @@ -33,8 +33,7 @@ class YatService { final yatRecords = []; try { - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); final resBody = json.decode(response.body) as Map; final results = resBody["result"] as Map; // Favour a subaddress over a standard address. @@ -43,7 +42,7 @@ class YatService { results[MONERO_STD_ADDRESS] ?? results[tag]) as Map; - if (yatRecord.isNotEmpty) { + if (yatRecord != null) { yatRecords.add(YatRecord.fromJson(yatRecord)); } diff --git a/lib/di.dart b/lib/di.dart index 5a7be0f1f..c8b002008 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -33,24 +33,18 @@ import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/haven/cw_haven.dart'; import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart'; import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart'; -import 'package:cake_wallet/src/screens/dev/network_requests.dart'; import 'package:cake_wallet/src/screens/dev/secure_preferences_page.dart'; import 'package:cake_wallet/src/screens/dev/shared_preferences_page.dart'; -import 'package:cake_wallet/src/screens/integrations/deuro/savings_page.dart'; import 'package:cake_wallet/src/screens/settings/background_sync_page.dart'; -import 'package:cake_wallet/src/screens/start_tor/start_tor_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart'; import 'package:cake_wallet/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart'; import 'package:cake_wallet/src/screens/wallet_connect/services/walletkit_service.dart'; -import 'package:cake_wallet/themes/core/theme_store.dart'; import 'package:cake_wallet/view_model/dev/monero_background_sync.dart'; import 'package:cake_wallet/view_model/dev/secure_preferences.dart'; import 'package:cake_wallet/view_model/dev/shared_preferences.dart'; -import 'package:cake_wallet/view_model/integrations/deuro_view_model.dart'; import 'package:cake_wallet/view_model/link_view_model.dart'; import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; -import 'package:cake_wallet/view_model/start_tor_view_model.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart'; import 'package:cake_wallet/entities/wallet_manager.dart'; @@ -141,6 +135,7 @@ import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; import 'package:cake_wallet/src/screens/settings/security_backup_page.dart'; import 'package:cake_wallet/src/screens/settings/silent_payments_settings.dart'; +import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -157,9 +152,11 @@ import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart'; import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_page.dart'; +import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/buy/buy_sell_view_model.dart'; import 'package:cake_wallet/view_model/animated_ur_model.dart'; import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; @@ -279,7 +276,6 @@ import 'src/screens/buy/buy_sell_page.dart'; import 'cake_pay/cake_pay_payment_credantials.dart'; import 'package:cake_wallet/view_model/dev/background_sync_logs_view_model.dart'; import 'package:cake_wallet/src/screens/dev/background_sync_logs_page.dart'; -import 'package:cake_wallet/core/trade_monitor.dart'; final getIt = GetIt.instance; @@ -329,11 +325,6 @@ Future setup({ if (!_isSetupFinished) { getIt.registerSingletonAsync(() => SharedPreferences.getInstance()); getIt.registerSingleton(secureStorage); - getIt.registerSingletonAsync(() async { - final store = ThemeStore(); - await store.loadThemePreferences(); - return store; - }); } final isBitcoinBuyEnabled = (secrets.wyreSecretKey.isNotEmpty) && @@ -344,6 +335,10 @@ Future setup({ nodeSource: _nodeSource, powNodeSource: _powNodeSource, isBitcoinBuyEnabled: isBitcoinBuyEnabled, + // Enforce darkTheme on platforms other than mobile till the design for other themes is completed + initialTheme: responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile + ? null + : ThemeList.darkTheme, ); if (_isSetupFinished) { @@ -361,8 +356,7 @@ Future setup({ authenticationStore: getIt.get(), walletList: getIt.get(), settingsStore: getIt.get(), - nodeListStore: getIt.get(), - themeStore: getIt.get())); + nodeListStore: getIt.get())); getIt.registerSingleton( TradesStore(tradesSource: _tradesSource, settingsStore: getIt.get())); getIt.registerSingleton( @@ -512,42 +506,19 @@ Future setup({ settingsStore: getIt.get(), fiatConvertationStore: getIt.get())); - getIt.registerFactory( - () => ExchangeViewModel( - getIt.get(), - _tradesSource, - getIt.get(), - getIt.get(), - getIt.get().settingsStore, - getIt.get(), - getIt.get(), - getIt.get(), - ), - ); - - getIt.registerSingleton( - TradeMonitor( - tradesStore: getIt.get(), - trades: _tradesSource, - appStore: getIt.get(), - preferences: getIt.get(), - ), - ); - getIt.registerFactory(() => DashboardViewModel( - tradeMonitor: getIt.get(), - balanceViewModel: getIt.get(), - appStore: getIt.get(), - tradesStore: getIt.get(), - tradeFilterStore: getIt.get(), - transactionFilterStore: getIt.get(), - settingsStore: settingsStore, - yatStore: getIt.get(), - ordersStore: getIt.get(), - anonpayTransactionsStore: getIt.get(), - payjoinTransactionsStore: getIt.get(), - sharedPreferences: getIt.get(), - keyService: getIt.get())); + balanceViewModel: getIt.get(), + appStore: getIt.get(), + tradesStore: getIt.get(), + tradeFilterStore: getIt.get(), + transactionFilterStore: getIt.get(), + settingsStore: settingsStore, + yatStore: getIt.get(), + ordersStore: getIt.get(), + anonpayTransactionsStore: getIt.get(), + payjoinTransactionsStore: getIt.get(), + sharedPreferences: getIt.get(), + keyService: getIt.get())); getIt.registerFactory( () => AuthService( @@ -692,6 +663,7 @@ Future setup({ return walletKitService; }); + getIt.registerFactory(() => NFTViewModel(appStore, getIt.get())); getIt.registerFactory(() => BalancePage( nftViewModel: getIt.get(), dashboardViewModel: getIt.get(), @@ -929,7 +901,7 @@ Future setup({ getIt.get(param1: account))); getIt.registerFactory(() => - DisplaySettingsViewModel(getIt.get(), getIt.get())); + DisplaySettingsViewModel(getIt.get())); getIt.registerFactory(() => SilentPaymentsSettingsViewModel(getIt.get(), getIt.get().wallet!)); @@ -1058,13 +1030,13 @@ Future setup({ getIt.get().wallet!.isHardwareWallet ? getIt.get() : null)); getIt.registerFactory(() => MoonPayProvider( - appStore: getIt.get(), + settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!, isTestEnvironment: kDebugMode, )); getIt.registerFactory(() => OnRamperBuyProvider( - getIt.get(), + getIt.get().settingsStore, wallet: getIt.get().wallet!, )); @@ -1078,6 +1050,19 @@ Future setup({ getIt.registerFactoryParam((title, uri) => WebViewPage(title, uri)); + getIt.registerFactory( + () => ExchangeViewModel( + getIt.get(), + _tradesSource, + getIt.get(), + getIt.get(), + getIt.get().settingsStore, + getIt.get(), + getIt.get(), + getIt.get(), + ), + ); + getIt.registerFactory( () => FeesViewModel( getIt.get(), @@ -1251,7 +1236,7 @@ Future setup({ TradeDetailsViewModel( tradeForDetails: trade, trades: _tradesSource, - appStore: getIt.get())); + settingsStore: getIt.get())); getIt.registerFactory(() => CakeFeaturesViewModel(getIt.get())); @@ -1446,7 +1431,7 @@ Future setup({ (AnonpayInvoiceInfo anonpayInvoiceInfo, _) => AnonpayDetailsViewModel( anonPayApi: getIt.get(), anonpayInvoiceInfo: anonpayInvoiceInfo, - themeStore: getIt.get(), + settingsStore: getIt.get(), )); getIt.registerFactoryParam( @@ -1455,7 +1440,7 @@ Future setup({ sessionId, transactionInfo, payjoinSessionSource: _payjoinSessionSource, - themeStore: getIt.get(), + settingsStore: getIt.get(), )); getIt.registerFactoryParam( @@ -1496,7 +1481,7 @@ Future setup({ () => WalletConnectConnectionsView(walletKitService: getIt.get()), ); - getIt.registerFactory(() => NFTViewModel(appStore, getIt.get())); + getIt.registerFactory(() => TorPage(getIt.get())); getIt.registerFactory(() => SignViewModel(getIt.get().wallet!)); @@ -1514,13 +1499,5 @@ Future setup({ getIt.registerFactory(() => DevBackgroundSyncLogsPage(getIt.get())); - getIt.registerFactory(() => DevNetworkRequests()); - - getIt.registerFactory(() => StartTorPage(StartTorViewModel(),)); - - getIt.registerFactory(() => DEuroViewModel(getIt())); - - getIt.registerFactory(() => DEuroSavingsPage(getIt())); - _isSetupFinished = true; } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index a5dfec97b..45234d5ec 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -37,7 +37,7 @@ const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum-rpc.publicnode.com'; const polygonDefaultNodeUri = 'polygon-bor-rpc.publicnode.com'; const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; -const nanoDefaultNodeUri = 'rpc.nano.to'; +const nanoDefaultNodeUri = 'nano.nownodes.io'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; const solanaDefaultNodeUri = 'solana-mainnet.core.chainstack.com'; const tronDefaultNodeUri = 'api.trongrid.io'; diff --git a/lib/entities/ens_record.dart b/lib/entities/ens_record.dart index 78b0f4178..512244c1b 100644 --- a/lib/entities/ens_record.dart +++ b/lib/entities/ens_record.dart @@ -1,16 +1,14 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:ens_dart/ens_dart.dart'; +import 'package:http/http.dart'; import 'package:web3dart/web3dart.dart'; class EnsRecord { - static Future fetchEnsAddress(String name, {WalletBase? wallet}) async { - Web3Client? _client; if (wallet != null && wallet.type == WalletType.ethereum) { @@ -22,9 +20,7 @@ class EnsRecord { } if (_client == null) { - late final client = ProxyWrapper().getHttpIOClient(); - - _client = Web3Client("https://ethereum-rpc.publicnode.com", client); + _client = Web3Client("https://ethereum-rpc.publicnode.com", Client()); } try { diff --git a/lib/entities/fio_address_provider.dart b/lib/entities/fio_address_provider.dart index dcfd79c96..a88804c97 100644 --- a/lib/entities/fio_address_provider.dart +++ b/lib/entities/fio_address_provider.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; class FioAddressProvider { static const apiAuthority = 'fio.blockpane.com'; @@ -13,17 +13,13 @@ class FioAddressProvider { final body = {"fio_name": fioAddress}; final uri = Uri.https(apiAuthority, availCheck); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); + final response = + await http.post(uri, headers: headers, body: json.encode(body)); if (response.statusCode != 200) { return isFioRegistered; } - final responseJSON = json.decode(response.body) as Map; isFioRegistered = responseJSON['is_registered'] as int == 1; @@ -39,13 +35,9 @@ class FioAddressProvider { }; final uri = Uri.https(apiAuthority, getAddress); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); + final response = + await http.post(uri, headers: headers, body: json.encode(body)); - if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; final error = responseJSON['error'] as String; diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 9fd1481a5..0cb2e4058 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -29,7 +29,7 @@ class MainActions { static MainActions showWalletsAction = MainActions._( name: (context) => S.of(context).wallets, - image: 'assets/images/wallet_icon.png', + image: 'assets/images/wallet_new.png', onTap: (BuildContext context, DashboardViewModel viewModel) async { Navigator.pushNamed( context, @@ -42,7 +42,7 @@ class MainActions { static MainActions receiveAction = MainActions._( name: (context) => S.of(context).receive, - image: 'assets/images/receive.png', + image: 'assets/images/received.png', onTap: (BuildContext context, DashboardViewModel viewModel) async { Navigator.pushNamed(context, Routes.addressPage); }, @@ -50,7 +50,7 @@ class MainActions { static MainActions swapAction = MainActions._( name: (context) => S.of(context).swap, - image: 'assets/images/swap.png', + image: 'assets/images/transfer.png', isEnabled: (viewModel) => viewModel.isEnabledSwapAction, canShow: (viewModel) => viewModel.hasSwapAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { @@ -62,7 +62,7 @@ class MainActions { static MainActions sendAction = MainActions._( name: (context) => S.of(context).send, - image: 'assets/images/send2.png', + image: 'assets/images/upload.png', isEnabled: (viewModel) => viewModel.canSend, onTap: (BuildContext context, DashboardViewModel viewModel) async { Navigator.pushNamed(context, Routes.send); @@ -70,8 +70,8 @@ class MainActions { ); static MainActions tradeAction = MainActions._( - name: (context) => S.of(context).buy, - image: 'assets/images/buy.png', + name: (context) => S.of(context).exchange, + image: 'assets/images/buy_sell.png', isEnabled: (viewModel) => viewModel.isEnabledTradeAction, canShow: (viewModel) => viewModel.hasTradeAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 01e6322cc..3fbbe0709 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -165,19 +165,13 @@ class AddressResolver { "zone" ]; - static String? extractAddressByType( - {required String raw, - required CryptoCurrency type, - bool requireSurroundingWhitespaces = true}) { - var addressPattern = AddressValidator.getAddressFromStringPattern(type); + static String? extractAddressByType({required String raw, required CryptoCurrency type}) { + final addressPattern = AddressValidator.getAddressFromStringPattern(type); if (addressPattern == null) { throw Exception('Unexpected token: $type for getAddressFromStringPattern'); } - if (requireSurroundingWhitespaces) - addressPattern = "$BEFORE_REGEX$addressPattern$AFTER_REGEX"; - final match = RegExp(addressPattern, multiLine: true).firstMatch(raw); return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'), (Match match) { diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 0f3c1fe48..494888a86 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -24,7 +24,6 @@ class PreferencesKey { static const shouldSaveRecipientAddressKey = 'save_recipient_address'; static const isAppSecureKey = 'is_app_secure'; static const disableTradeOption = 'disable_buy'; - static const disableAutomaticExchangeStatusUpdates = 'disable_automatic_exchange_status_updates'; static const disableBulletinKey = 'disable_bulletin'; static const walletListOrder = 'wallet_list_order'; static const contactListOrder = 'contact_list_order'; @@ -35,7 +34,6 @@ class PreferencesKey { static const disableExchangeKey = 'disable_exchange'; static const exchangeStatusKey = 'exchange_status'; static const currentTheme = 'current_theme'; - static const themeMode = 'theme_mode'; static const displayActionListModeKey = 'display_list_mode'; static const currentPinLength = 'current_pin_length'; static const currentLanguageCode = 'language_code'; @@ -66,7 +64,6 @@ class PreferencesKey { static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; static const syncModeKey = 'sync_mode'; static const syncAllKey = 'sync_all'; - static const builtinTorKey = 'builtin_tor'; static const lastPopupDate = 'last_popup_date'; static const lastAppReviewDate = 'last_app_review_date'; static const sortBalanceBy = 'sort_balance_by'; @@ -86,7 +83,6 @@ class PreferencesKey { static const lookupsENS = 'looks_up_ens'; static const lookupsWellKnown = 'looks_up_well_known'; static const usePayjoin = 'use_payjoin'; - static const showPayjoinCard = 'show_payjoin_card'; static const showCameraConsent = 'show_camera_consent'; static const showDecredInfoCard = 'show_decred_info_card'; diff --git a/lib/entities/qr_scanner.dart b/lib/entities/qr_scanner.dart index 31353a8f8..c4d37ad6c 100644 --- a/lib/entities/qr_scanner.dart +++ b/lib/entities/qr_scanner.dart @@ -15,7 +15,7 @@ Future presentQRScanner(BuildContext context) async { try { final result = await Navigator.of(context).push( MaterialPageRoute( - builder: (context) { + builder:(context) { return BarcodeScannerSimple(); }, ), @@ -67,7 +67,7 @@ class _BarcodeScannerSimpleState extends State { void _handleBarcodeInternal(BarcodeCapture barcodes) { for (final barcode in barcodes.barcodes) { // don't handle unknown QR codes - if (barcode.rawValue?.trim().isEmpty ?? false == false) continue; + if (barcode.rawValue?.trim().isEmpty??false == false) continue; if (barcode.rawValue!.startsWith("ur:")) { if (urCodes.contains(barcode.rawValue)) continue; setState(() { @@ -81,8 +81,7 @@ class _BarcodeScannerSimpleState extends State { SchedulerBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pop(ur.inputs.join("\n")); }); - } - ; + }; } } if (urCodes.isNotEmpty) return; @@ -111,21 +110,18 @@ class _BarcodeScannerSimpleState extends State { ToggleFlashlightButton(controller: ctrl), ], ), - backgroundColor: Theme.of(context).colorScheme.surface, + backgroundColor: Colors.black, body: Stack( children: [ MobileScanner( onDetect: _handleBarcode, controller: ctrl, ), - if (ur.inputs.length != 0) - Center( - child: Text( + if (ur.inputs.length != 0) + Center(child: + Text( "${ur.inputs.length}/${ur.count}", - style: Theme.of(context) - .textTheme - .displayLarge - ?.copyWith(color: Theme.of(context).colorScheme.onSurface), + style: Theme.of(context).textTheme.displayLarge?.copyWith(color: Colors.white) ), ), SizedBox( @@ -162,6 +158,7 @@ class _BarcodeScannerSimpleState extends State { } } + class ToggleFlashlightButton extends StatelessWidget { const ToggleFlashlightButton({required this.controller, super.key}); @@ -202,9 +199,9 @@ class ToggleFlashlightButton extends StatelessWidget { }, ); case TorchState.unavailable: - return Icon( + return const Icon( Icons.no_flash, - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: Colors.grey, ); } }, @@ -329,14 +326,16 @@ class ProgressPainter extends CustomPainter { const fullAngle = 360.0; var startAngle = 0.0; for (int i = 0; i < urQrProgress.expectedPartCount.toInt(); i++) { - var sweepAngle = (1 / urQrProgress.expectedPartCount) * fullAngle * pi / 180.0; - drawSector( - canvas, urQrProgress.receivedPartIndexes.contains(i), rect, startAngle, sweepAngle); + var sweepAngle = + (1 / urQrProgress.expectedPartCount) * fullAngle * pi / 180.0; + drawSector(canvas, urQrProgress.receivedPartIndexes.contains(i), rect, + startAngle, sweepAngle); startAngle += sweepAngle; } } - void drawSector(Canvas canvas, bool isActive, Rect rect, double startAngle, double sweepAngle) { + void drawSector(Canvas canvas, bool isActive, Rect rect, double startAngle, + double sweepAngle) { final paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 diff --git a/lib/entities/seed_type.dart b/lib/entities/seed_type.dart index 22f0be045..0c5632875 100644 --- a/lib/entities/seed_type.dart +++ b/lib/entities/seed_type.dart @@ -2,19 +2,16 @@ import 'package:cw_core/enumerable_item.dart'; import 'package:cw_core/wallet_info.dart'; class MoneroSeedType extends EnumerableItem with Serializable { - const MoneroSeedType({required String title, required int raw, this.shortTitle}) - : super(title: title, raw: raw); - - final String? shortTitle; + const MoneroSeedType({required String title, required int raw}) : super(title: title, raw: raw); static const all = [legacy, polyseed, bip39]; static const defaultSeedType = polyseed; - static const legacy = MoneroSeedType(raw: 0, title: 'Legacy (25 words)', shortTitle: "Legacy"); - static const polyseed = MoneroSeedType(raw: 1, title: 'Polyseed (16 words)', shortTitle: "Polyseed"); + static const legacy = MoneroSeedType(raw: 0, title: 'Legacy (25 words)'); + static const polyseed = MoneroSeedType(raw: 1, title: 'Polyseed (16 words)'); static const wowneroSeed = MoneroSeedType(raw: 2, title: 'Wownero'); - static const bip39 = MoneroSeedType(raw: 3, title: 'BIP39 (12 words)', shortTitle: "BIP39"); + static const bip39 = MoneroSeedType(raw: 3, title: 'BIP39 (12 words)'); static MoneroSeedType deserialize({required int raw}) { switch (raw) { diff --git a/lib/entities/transaction_description.dart b/lib/entities/transaction_description.dart index 05f64820e..2ac573652 100644 --- a/lib/entities/transaction_description.dart +++ b/lib/entities/transaction_description.dart @@ -5,7 +5,7 @@ part 'transaction_description.g.dart'; @HiveType(typeId: TransactionDescription.typeId) class TransactionDescription extends HiveObject { - TransactionDescription({required this.id, this.recipientAddress, this.transactionNote, this.transactionKey}); + TransactionDescription({required this.id, this.recipientAddress, this.transactionNote}); static const typeId = TRANSACTION_TYPE_ID; static const boxName = 'TransactionDescriptions'; @@ -20,16 +20,12 @@ class TransactionDescription extends HiveObject { @HiveField(2) String? transactionNote; - @HiveField(3) - String? transactionKey; - String get note => transactionNote ?? ''; Map toJson() => { 'id': id, 'recipientAddress': recipientAddress, 'transactionNote': transactionNote, - 'transactionKey': transactionKey, }; factory TransactionDescription.fromJson(Map json) { @@ -37,7 +33,6 @@ class TransactionDescription extends HiveObject { id: json['id'] as String, recipientAddress: json['recipientAddress'] as String?, transactionNote: json['transactionNote'] as String?, - transactionKey: json['transactionKey'] as String?, ); } } diff --git a/lib/entities/unstoppable_domain_address.dart b/lib/entities/unstoppable_domain_address.dart index cf6eb8945..a047c85d9 100644 --- a/lib/entities/unstoppable_domain_address.dart +++ b/lib/entities/unstoppable_domain_address.dart @@ -1,16 +1,15 @@ import 'dart:convert'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; Future fetchUnstoppableDomainAddress(String domain, String ticker) async { var address = ''; try { final uri = Uri.parse("https://api.unstoppabledomains.com/profile/public/${Uri.encodeQueryComponent(domain)}?fields=records"); - final response = await ProxyWrapper().get(clearnetUri: uri); - - final jsonParsed = json.decode(response.body) as Map; + final jsonString = await http.read(uri); + final jsonParsed = json.decode(jsonString) as Map; if (jsonParsed["records"] == null) { throw Exception(".records response from $uri is empty"); }; diff --git a/lib/entities/wellknown_record.dart b/lib/entities/wellknown_record.dart index 6dd94440b..dbe808281 100644 --- a/lib/entities/wellknown_record.dart +++ b/lib/entities/wellknown_record.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; class WellKnownRecord { WellKnownRecord({ @@ -40,15 +40,14 @@ class WellKnownRecord { } // lookup domain/.well-known/nano-currency.json and check if it has a nano address: - final response = await ProxyWrapper().get( - clearnetUri: Uri.parse("https://$domain/.well-known/$jsonLocation.json?names=$name"), + final http.Response response = await http.get( + Uri.parse("https://$domain/.well-known/$jsonLocation.json?names=$name"), headers: {"Accept": "application/json"}, ); if (response.statusCode != 200) { return null; } - final Map decoded = json.decode(response.body) as Map; // Access the first element in the names array and retrieve its address diff --git a/lib/entities/zano_alias.dart b/lib/entities/zano_alias.dart index ec966e225..1ddf95178 100644 --- a/lib/entities/zano_alias.dart +++ b/lib/entities/zano_alias.dart @@ -1,14 +1,14 @@ import 'dart:convert'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; class ZanoAlias { static Future fetchZanoAliasAddress(String alias) async { try { final uri = Uri.parse("http://zano.cakewallet.com:11211/json_rpc"); - final response = await ProxyWrapper().post( - clearnetUri: uri, + final response = await http.post( + uri, body: json.encode({ "id": 0, "jsonrpc": "2.0", @@ -16,7 +16,6 @@ class ZanoAlias { "params": {"alias": alias} }), ); - final jsonParsed = json.decode(response.body) as Map; return jsonParsed['result']['alias_details']['address'] as String?; diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index a6a6a7205..40c7a0f77 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -67,7 +67,8 @@ class CWEthereum extends Ethereum { @override String getPublicKey(WalletBase wallet) { final privateKeyInUnitInt = (wallet as EthereumWallet).evmChainPrivateKey; - return privateKeyInUnitInt.address.hex; + final publicKey = privateKeyInUnitInt.address.hex; + return publicKey; } @override @@ -137,24 +138,29 @@ class CWEthereum extends Ethereum { } @override - List getERC20Currencies(WalletBase wallet) => - (wallet as EthereumWallet).erc20Currencies; + List getERC20Currencies(WalletBase wallet) { + final ethereumWallet = wallet as EthereumWallet; + return ethereumWallet.erc20Currencies; + } @override - Future addErc20Token(WalletBase wallet, CryptoCurrency token) => - (wallet as EthereumWallet).addErc20Token(token as Erc20Token); + Future addErc20Token(WalletBase wallet, CryptoCurrency token) async { + await (wallet as EthereumWallet).addErc20Token(token as Erc20Token); + } @override - Future deleteErc20Token(WalletBase wallet, CryptoCurrency token) => - (wallet as EthereumWallet).deleteErc20Token(token as Erc20Token); + Future deleteErc20Token(WalletBase wallet, CryptoCurrency token) async => + await (wallet as EthereumWallet).deleteErc20Token(token as Erc20Token); @override - Future removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) => - (wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token); + Future removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async => + await (wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token); @override - Future getErc20Token(WalletBase wallet, String contractAddress) => - (wallet as EthereumWallet).getErc20Token(contractAddress, 'eth'); + Future getErc20Token(WalletBase wallet, String contractAddress) async { + final ethereumWallet = wallet as EthereumWallet; + return await ethereumWallet.getErc20Token(contractAddress, 'eth'); + } @override CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { @@ -171,19 +177,23 @@ class CWEthereum extends Ethereum { } @override - void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) => - (wallet as EthereumWallet).updateScanProviderUsageState(isEnabled); + void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) { + (wallet as EthereumWallet).updateScanProviderUsageState(isEnabled); + } @override - Web3Client? getWeb3Client(WalletBase wallet) => (wallet as EthereumWallet).getWeb3Client(); + Web3Client? getWeb3Client(WalletBase wallet) { + return (wallet as EthereumWallet).getWeb3Client(); + } - @override String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress; @override - void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection) { + void setLedgerConnection( + WalletBase wallet, ledger.LedgerConnection connection) { ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials) - .setLedgerConnection(connection, wallet.walletInfo.derivationInfo?.derivationPath); + .setLedgerConnection( + connection, wallet.walletInfo.derivationInfo?.derivationPath); } @override @@ -202,49 +212,4 @@ class CWEthereum extends Ethereum { List getDefaultTokenContractAddresses() { return DefaultEthereumErc20Tokens().initialErc20Tokens.map((e) => e.contractAddress).toList(); } - - - @override - bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress) { - final ethereumWallet = wallet as EthereumWallet; - return ethereumWallet.erc20Currencies.any((element) => element.contractAddress.toLowerCase() == contractAddress.toLowerCase()); - } - - Future createTokenApproval(WalletBase wallet, BigInt amount, String spender, - CryptoCurrency token, TransactionPriority priority) => - (wallet as EVMChainWallet).createApprovalTransaction( - amount, spender, token, priority as EVMChainTransactionPriority); - - // Integrations - @override - Future getDEuroSavingsBalance(WalletBase wallet) => - DEuro(wallet as EthereumWallet).savingsBalance; - - @override - Future getDEuroAccruedInterest(WalletBase wallet) => - DEuro(wallet as EthereumWallet).accruedInterest; - - @override - Future getDEuroInterestRate(WalletBase wallet) => - DEuro(wallet as EthereumWallet).interestRate; - - @override - Future getDEuroSavingsApproved(WalletBase wallet) => - DEuro(wallet as EthereumWallet).approvedBalance; - - @override - Future addDEuroSaving( - WalletBase wallet, BigInt amount, TransactionPriority priority) => - DEuro(wallet as EthereumWallet) - .depositSavings(amount, priority as EVMChainTransactionPriority); - - @override - Future removeDEuroSaving( - WalletBase wallet, BigInt amount, TransactionPriority priority) => - DEuro(wallet as EthereumWallet) - .withdrawSavings(amount, priority as EVMChainTransactionPriority); - - @override - Future enableDEuroSaving(WalletBase wallet, TransactionPriority priority) => - DEuro(wallet as EthereumWallet).enableSavings(priority as EVMChainTransactionPriority); } diff --git a/lib/exchange/provider/chainflip_exchange_provider.dart b/lib/exchange/provider/chainflip_exchange_provider.dart index c2e2f385c..a2c27b745 100644 --- a/lib/exchange/provider/chainflip_exchange_provider.dart +++ b/lib/exchange/provider/chainflip_exchange_provider.dart @@ -12,7 +12,7 @@ import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:hive/hive.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; class ChainflipExchangeProvider extends ExchangeProvider { ChainflipExchangeProvider({required this.tradesStore}) @@ -275,8 +275,7 @@ class ChainflipExchangeProvider extends ExchangeProvider { Future> _getRequest(String path, Map params) async { final uri = Uri.https(_baseURL, path, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri); if ((response.statusCode != 200) || (response.body.contains('error'))) { throw Exception('Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}'); @@ -288,8 +287,7 @@ class ChainflipExchangeProvider extends ExchangeProvider { Future?> _getStatus(Map params) async { final uri = Uri.https(_baseURL, _txInfoPath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri); if (response.statusCode == 404) return null; diff --git a/lib/exchange/provider/changenow_exchange_provider.dart b/lib/exchange/provider/changenow_exchange_provider.dart index dbc4cc3ab..79f8d70d4 100644 --- a/lib/exchange/provider/changenow_exchange_provider.dart +++ b/lib/exchange/provider/changenow_exchange_provider.dart @@ -11,11 +11,12 @@ import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/distribution_info.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:http/http.dart'; class ChangeNowExchangeProvider extends ExchangeProvider { ChangeNowExchangeProvider({required SettingsStore settingsStore}) @@ -29,7 +30,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { ]; static final apiKey = - isMoneroOnly ? secrets.changeNowMoneroApiKey : secrets.changeNowCakeWalletApiKey; + DeviceInfo.instance.isMobile ? secrets.changeNowApiKey : secrets.changeNowApiKeyDesktop; static const apiAuthority = 'api.changenow.io'; static const createTradePath = '/v2/exchange'; static const findTradeByIdPath = '/v2/exchange/by-id'; @@ -72,7 +73,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { 'flow': _getFlow(isFixedRateMode) }; final uri = Uri.https(apiAuthority, rangePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); + final response = await get(uri, headers: headers); if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; @@ -117,8 +118,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { params['fromAmount'] = amount.toString(); final uri = Uri.https(apiAuthority, estimatedAmountPath, params); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); - + final response = await get(uri, headers: headers); final responseJSON = json.decode(response.body) as Map; final fromAmount = double.parse(responseJSON['fromAmount'].toString()); final toAmount = double.parse(responseJSON['toAmount'].toString()); @@ -177,11 +177,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { } final uri = Uri.https(apiAuthority, createTradePath); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); + final response = await post(uri, headers: headers, body: json.encode(body)); if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; @@ -224,7 +220,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final headers = {apiHeaderKey: apiKey}; final params = {'id': id}; final uri = Uri.https(apiAuthority, findTradeByIdPath, params); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); + final response = await get(uri, headers: headers); if (response.statusCode == 404) throw TradeNotFoundException(id, provider: description); diff --git a/lib/exchange/provider/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart index 0b7491bf5..43f63b8ca 100644 --- a/lib/exchange/provider/exolix_exchange_provider.dart +++ b/lib/exchange/provider/exolix_exchange_provider.dart @@ -9,15 +9,14 @@ import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:http/http.dart'; class ExolixExchangeProvider extends ExchangeProvider { ExolixExchangeProvider() : super(pairList: supportedPairs(_notSupported)); - static final apiKey = isMoneroOnly ? secrets.exolixMoneroApiKey : secrets.exolixCakeWalletApiKey; + static final apiKey = secrets.exolixApiKey; static const apiBaseUrl = 'exolix.com'; static const transactionsPath = '/api/v2/transactions'; static const ratePath = '/api/v2/rate'; @@ -87,9 +86,8 @@ class ExolixExchangeProvider extends ExchangeProvider { // Maximum of 2 attempts to fetch limits for (int i = 0; i < 2; i++) { final uri = Uri.https(apiBaseUrl, ratePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - - + final response = await get(uri); + if (response.statusCode == 200) { final responseJSON = json.decode(response.body) as Map; final minAmount = responseJSON['minAmount']; @@ -135,8 +133,7 @@ class ExolixExchangeProvider extends ExchangeProvider { params['amount'] = amount.toString(); final uri = Uri.https(apiBaseUrl, ratePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); final responseJSON = json.decode(response.body) as Map; if (response.statusCode != 200) { @@ -175,12 +172,7 @@ class ExolixExchangeProvider extends ExchangeProvider { body['amount'] = request.fromAmount; final uri = Uri.https(apiBaseUrl, transactionsPath); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); - + final response = await post(uri, headers: headers, body: json.encode(body)); if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; @@ -222,8 +214,8 @@ class ExolixExchangeProvider extends ExchangeProvider { Future findTradeById({required String id}) async { final findTradeByIdPath = '$transactionsPath/$id'; final uri = Uri.https(apiBaseUrl, findTradeByIdPath); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); + if (response.statusCode == 404) throw TradeNotFoundException(id, provider: description); if (response.statusCode == 400) { diff --git a/lib/exchange/provider/letsexchange_exchange_provider.dart b/lib/exchange/provider/letsexchange_exchange_provider.dart index 1fe1e9e35..d07297fcf 100644 --- a/lib/exchange/provider/letsexchange_exchange_provider.dart +++ b/lib/exchange/provider/letsexchange_exchange_provider.dart @@ -10,9 +10,9 @@ import 'package:cake_wallet/exchange/trade_not_created_exception.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:http/http.dart' as http; class LetsExchangeExchangeProvider extends ExchangeProvider { LetsExchangeExchangeProvider() : super(pairList: supportedPairs(_notSupported)); @@ -152,11 +152,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { final uri = Uri.https(_baseUrl, isFixedRateMode ? _createTransactionRevertPath : _createTransactionPath, tradeParams); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - ); - + final response = await http.post(uri, headers: headers); if (response.statusCode != 200) { throw Exception('LetsExchange create trade failed: ${response.body}'); @@ -222,8 +218,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { }; final url = Uri.https(_baseUrl, '$_getTransactionPath/$id'); - final response = await ProxyWrapper().get(clearnetUri: url, headers: headers); - + final response = await http.get(url, headers: headers); if (response.statusCode != 200) { throw Exception('LetsExchange fetch trade failed: ${response.body}'); @@ -271,11 +266,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { try { final uri = Uri.https(_baseUrl, isFixedRateMode ? _infoRevertPath : _infoPath, params); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - ); - + final response = await http.post(uri, headers: headers); if (response.statusCode != 200) { throw Exception('LetsExchange fetch info failed: ${response.body}'); } diff --git a/lib/exchange/provider/sideshift_exchange_provider.dart b/lib/exchange/provider/sideshift_exchange_provider.dart index 3c9b2d951..12ec59100 100644 --- a/lib/exchange/provider/sideshift_exchange_provider.dart +++ b/lib/exchange/provider/sideshift_exchange_provider.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; @@ -10,9 +11,9 @@ import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:http/http.dart'; class SideShiftExchangeProvider extends ExchangeProvider { SideShiftExchangeProvider() : super(pairList: supportedPairs(_notSupported)); @@ -59,8 +60,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { Future checkIsAvailable() async { const url = apiBaseUrl + permissionPath; final uri = Uri.parse(url); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); + if (response.statusCode == 500) { final responseJSON = json.decode(response.body) as Map; final error = responseJSON['error']['message'] as String; @@ -89,8 +90,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { "$apiBaseUrl$rangePath/${fromCurrency.title.toLowerCase()}-$fromNetwork/${toCurrency.title.toLowerCase()}-$toNetwork"; final uri = Uri.parse(url); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); if (response.statusCode == 500) { final responseJSON = json.decode(response.body) as Map; @@ -137,8 +137,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork?amount=$amount"; final uri = Uri.parse(url); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); final responseJSON = json.decode(response.body) as Map; if (response.statusCode == 500) { @@ -187,12 +186,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { final headers = {'Content-Type': 'application/json'}; final uri = Uri.parse(url); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); - + final response = await post(uri, headers: headers, body: json.encode(body)); if (response.statusCode != 201) { if (response.statusCode == 400) { @@ -233,8 +227,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { Future findTradeById({required String id}) async { final url = apiBaseUrl + orderPath + '/' + id; final uri = Uri.parse(url); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); + if (response.statusCode == 404) { throw TradeNotFoundException(id, provider: description); } @@ -287,12 +281,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { 'depositNetwork': _networkFor(request.fromCurrency), }; final uri = Uri.parse(url); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); - + final response = await post(uri, headers: headers, body: json.encode(body)); if (response.statusCode != 201) { if (response.statusCode == 400) { diff --git a/lib/exchange/provider/simpleswap_exchange_provider.dart b/lib/exchange/provider/simpleswap_exchange_provider.dart index cc02ac799..5391d5f89 100644 --- a/lib/exchange/provider/simpleswap_exchange_provider.dart +++ b/lib/exchange/provider/simpleswap_exchange_provider.dart @@ -11,8 +11,8 @@ import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cake_wallet/utils/device_info.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:http/http.dart'; class SimpleSwapExchangeProvider extends ExchangeProvider { SimpleSwapExchangeProvider() : super(pairList: supportedPairs(_notSupported)); @@ -48,7 +48,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { @override Future checkIsAvailable() async { final uri = Uri.https(apiAuthority, getEstimatePath, {'api_key': apiKey}); - final response = await ProxyWrapper().get(clearnetUri: uri); + final response = await get(uri); return !(response.statusCode == 403); } @@ -66,8 +66,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { }; final uri = Uri.https(apiAuthority, rangePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); if (response.statusCode == 500) { final responseJSON = json.decode(response.body) as Map; @@ -105,10 +104,10 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { 'fixed': isFixedRateMode.toString() }; final uri = Uri.https(apiAuthority, getEstimatePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); if (response.body == "null") return 0.00; + final data = json.decode(response.body) as String; return double.parse(data) / amount; @@ -135,12 +134,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { }; final uri = Uri.https(apiAuthority, createExchangePath, params); - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: headers, - body: json.encode(body), - ); - + final response = await post(uri, headers: headers, body: json.encode(body)); if (response.statusCode != 200 && response.statusCode != 201) { if (response.statusCode == 400) { @@ -182,9 +176,8 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { Future findTradeById({required String id}) async { final params = {'api_key': apiKey, 'id': id}; final uri = Uri.https(apiAuthority, getExchangePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - - + final response = await get(uri); + if (response.statusCode == 404) { throw TradeNotFoundException(id, provider: description); } diff --git a/lib/exchange/provider/stealth_ex_exchange_provider.dart b/lib/exchange/provider/stealth_ex_exchange_provider.dart index 8c7efae65..11b8d768a 100644 --- a/lib/exchange/provider/stealth_ex_exchange_provider.dart +++ b/lib/exchange/provider/stealth_ex_exchange_provider.dart @@ -10,8 +10,8 @@ import 'package:cake_wallet/exchange/trade_not_created_exception.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:http/http.dart' as http; class StealthExExchangeProvider extends ExchangeProvider { StealthExExchangeProvider() : super(pairList: supportedPairs(_notSupported)); @@ -63,12 +63,8 @@ class StealthExExchangeProvider extends ExchangeProvider { }; try { - final response = await ProxyWrapper().post( - clearnetUri: Uri.parse(_baseUrl + _rangePath), - headers: headers, - body: json.encode(body), - ); - + final response = await http.post(Uri.parse(_baseUrl + _rangePath), + headers: headers, body: json.encode(body)); if (response.statusCode != 200) { throw Exception('StealthEx fetch limits failed: ${response.body}'); } @@ -138,12 +134,8 @@ class StealthExExchangeProvider extends ExchangeProvider { 'additional_fee_percent': _additionalFeePercent, }; - final response = await ProxyWrapper().post( - clearnetUri: Uri.parse(_baseUrl + _exchangesPath), - headers: headers, - body: json.encode(body), - ); - + final response = await http.post(Uri.parse(_baseUrl + _exchangesPath), + headers: headers, body: json.encode(body)); if (response.statusCode != 201) { throw Exception('StealthEx create trade failed: ${response.body}'); @@ -210,9 +202,8 @@ class StealthExExchangeProvider extends ExchangeProvider { final headers = {'Authorization': apiKey, 'Content-Type': 'application/json'}; final uri = Uri.parse('$_baseUrl$_exchangesPath/$id'); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers); - - + final response = await http.get(uri, headers: headers); + if (response.statusCode != 200) { throw Exception('StealthEx fetch trade failed: ${response.body}'); } @@ -269,12 +260,8 @@ class StealthExExchangeProvider extends ExchangeProvider { }; try { - final response = await ProxyWrapper().post( - clearnetUri: Uri.parse(_baseUrl + _amountPath), - headers: headers, - body: json.encode(body), - ); - + final response = await http.post(Uri.parse(_baseUrl + _amountPath), + headers: headers, body: json.encode(body)); if (response.statusCode != 200) return {}; final responseJSON = json.decode(response.body) as Map; final rate = responseJSON['rate'] as Map?; diff --git a/lib/exchange/provider/swaptrade_exchange_provider.dart b/lib/exchange/provider/swaptrade_exchange_provider.dart index f6c8332db..b86482335 100644 --- a/lib/exchange/provider/swaptrade_exchange_provider.dart +++ b/lib/exchange/provider/swaptrade_exchange_provider.dart @@ -10,9 +10,9 @@ import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:http/http.dart'; class SwapTradeExchangeProvider extends ExchangeProvider { SwapTradeExchangeProvider() : super(pairList: supportedPairs(_notSupported)); @@ -47,10 +47,10 @@ class SwapTradeExchangeProvider extends ExchangeProvider { String get title => 'SwapTrade'; @override - bool get isAvailable => true; + bool get isAvailable => false; @override - bool get isEnabled => true; + bool get isEnabled => false; @override bool get supportsFixedRate => false; @@ -59,7 +59,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider { ExchangeProviderDescription get description => ExchangeProviderDescription.swapTrade; @override - Future checkIsAvailable() async => true; + Future checkIsAvailable() async => false; @override Future fetchLimits({ @@ -69,8 +69,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider { }) async { try { final uri = Uri.https(apiAuthority, getCoins); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); final responseJSON = json.decode(response.body) as Map; @@ -117,12 +116,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider { }; final uri = Uri.https(apiAuthority, getRate, params); - final response = await ProxyWrapper().post( - clearnetUri: uri, - body: json.encode(body), - headers: headers, - ); - + final response = await post(uri, body: body, headers: headers); final responseBody = json.decode(response.body) as Map; if (response.statusCode != 200) @@ -159,12 +153,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider { }; final uri = Uri.https(apiAuthority, createOrder, params); - final response = await ProxyWrapper().post( - clearnetUri: uri, - body: json.encode(body), - headers: headers, - ); - + final response = await post(uri, body: body, headers: headers); final responseBody = json.decode(response.body) as Map; if (response.statusCode == 400 || responseBody["success"] == false) { @@ -207,12 +196,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider { }; final uri = Uri.https(apiAuthority, order, params); - final response = await ProxyWrapper().post( - clearnetUri: uri, - body: json.encode(body), - headers: headers, - ); - + final response = await post(uri, body: body, headers: headers); final responseBody = json.decode(response.body) as Map; if (response.statusCode == 400 || responseBody["success"] == false) { diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart index 16246abac..aa7ab2d27 100644 --- a/lib/exchange/provider/thorchain_exchange.provider.dart +++ b/lib/exchange/provider/thorchain_exchange.provider.dart @@ -7,10 +7,10 @@ import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:hive/hive.dart'; +import 'package:http/http.dart' as http; class ThorChainExchangeProvider extends ExchangeProvider { ThorChainExchangeProvider({required this.tradesStore}) @@ -23,7 +23,6 @@ class ThorChainExchangeProvider extends ExchangeProvider { // CryptoCurrency.eth, CryptoCurrency.ltc, CryptoCurrency.bch, - CryptoCurrency.usdtbsc, // CryptoCurrency.aave, // CryptoCurrency.dai, // CryptoCurrency.gusd, @@ -165,8 +164,7 @@ class ThorChainExchangeProvider extends ExchangeProvider { if (id.isEmpty) throw Exception('Trade id is empty'); final formattedId = id.startsWith('0x') ? id.substring(2) : id; final uri = Uri.https(_baseNodeURL, '$_txInfoPath$formattedId'); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri); if (response.statusCode == 404) { throw Exception('Trade not found for id: $formattedId'); @@ -219,8 +217,8 @@ class ThorChainExchangeProvider extends ExchangeProvider { static Future?>? lookupAddressByName(String name) async { final uri = Uri.https(_baseURL, '$_nameLookUpPath$name'); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri); + if (response.statusCode != 200) { return null; } @@ -246,8 +244,8 @@ class ThorChainExchangeProvider extends ExchangeProvider { Future> _getSwapQuote(Map params) async { Uri uri = Uri.https(_baseNodeURL, _quotePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri); + if (response.statusCode != 200) { throw Exception('Unexpected HTTP status: ${response.statusCode}'); } @@ -260,7 +258,7 @@ class ThorChainExchangeProvider extends ExchangeProvider { } String _normalizeCurrency(CryptoCurrency currency) { - final networkTitle = currency.tag == 'ETH' ? 'ETH' : currency.tag ?? currency.title; + final networkTitle = currency.tag == 'ETH' ? 'ETH' : currency.title; return '$networkTitle.${currency.title}'; } diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index cc8d8fa60..26a9b2e35 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -8,10 +8,9 @@ import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:http/http.dart'; class TrocadorExchangeProvider extends ExchangeProvider { TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}}) @@ -52,10 +51,9 @@ class TrocadorExchangeProvider extends ExchangeProvider { CryptoCurrency.zaddr, ]; - static final apiKey = isMoneroOnly ? secrets.trocadorMoneroApiKey : secrets.trocadorApiKey; + static const apiKey = secrets.trocadorApiKey; + static const onionApiAuthority = 'trocadorfyhlu27aefre5u7zri66gudtzdyelymftvr4yjwcxhfaqsid.onion'; static const clearNetAuthority = 'api.trocador.app'; - static const onionApiAuthority = clearNetAuthority; - // static const onionApiAuthority = 'trocadorfyhlu27aefre5u7zri66gudtzdyelymftvr4yjwcxhfaqsid.onion'; static const markup = secrets.trocadorExchangeMarkup; static const newRatePath = '/new_rate'; static const createTradePath = '/new_trade'; @@ -99,8 +97,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { }; final uri = await _getUri(coinPath, params); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: {'API-Key': apiKey}); - + final response = await get(uri, headers: {'API-Key': apiKey}); if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); @@ -141,10 +138,12 @@ class TrocadorExchangeProvider extends ExchangeProvider { }; final uri = await _getUri(newRatePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: {'API-Key': apiKey}); - + final response = await get(uri, headers: {'API-Key': apiKey}); final responseJSON = json.decode(response.body) as Map; + + if (responseJSON['error'] != null) throw Exception(responseJSON['error']); + final fromAmount = double.parse(responseJSON['amount_from'].toString()); final toAmount = double.parse(responseJSON['amount_to'].toString()); final rateId = responseJSON['trade_id'] as String? ?? ''; @@ -207,9 +206,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { params['provider'] = _provider.first as String; final uri = await _getUri(createTradePath, params); - final response = await ProxyWrapper().get(clearnetUri: uri, headers: {'API-Key': apiKey}); - - + final response = await get(uri, headers: {'API-Key': apiKey}); + if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; final error = responseJSON['error'] as String; @@ -232,7 +230,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { final providerName = responseJSON['provider'] as String; final amount = responseJSON['amount_from']?.toString(); final receiveAmount = responseJSON['amount_to']?.toString(); - final addressProviderMemo = responseJSON['address_provider_memo'] as String?; return Trade( id: id, @@ -250,17 +247,15 @@ class TrocadorExchangeProvider extends ExchangeProvider { receiveAmount: receiveAmount ?? request.toAmount, payoutAddress: payoutAddress, isSendAll: isSendAll, - extraId: addressProviderMemo, ); } @override Future findTradeById({required String id}) async { final uri = await _getUri(tradePath, {'id': id}); - return ProxyWrapper().get(clearnetUri: uri, headers: {'API-Key': apiKey}).then((response) async { + return get(uri, headers: {'API-Key': apiKey}).then((response) { if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - final responseListJson = json.decode(response.body) as List; final responseJSON = responseListJson.first; @@ -295,8 +290,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { Future> fetchProviders() async { final uri = await _getUri(providersListPath, {'api_key': apiKey}); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await get(uri); if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); @@ -348,8 +342,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { return 'TRC20'; case 'LN': return 'Lightning'; - case 'BSC': - return 'BEP20'; default: return tag.toLowerCase(); } @@ -361,7 +353,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { if (useTorOnly) return uri; try { - await ProxyWrapper().get(clearnetUri: uri); + await get(uri); return uri; } catch (e) { diff --git a/lib/exchange/provider/xoswap_exchange_provider.dart b/lib/exchange/provider/xoswap_exchange_provider.dart index e70eab568..5611d6855 100644 --- a/lib/exchange/provider/xoswap_exchange_provider.dart +++ b/lib/exchange/provider/xoswap_exchange_provider.dart @@ -10,7 +10,8 @@ import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:http/http.dart' as http; + class XOSwapExchangeProvider extends ExchangeProvider { XOSwapExchangeProvider() : super(pairList: supportedPairs(_notSupported)); @@ -71,8 +72,7 @@ class XOSwapExchangeProvider extends ExchangeProvider { final uri = Uri.https(_apiAuthority, _apiPath + _assets, {'networks': normalizedNetwork, 'query': currency.title}); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri, headers: _headers); if (response.statusCode != 200) { throw Exception('Failed to fetch assets for ${currency.title} on ${currency.tag}'); } @@ -102,8 +102,7 @@ class XOSwapExchangeProvider extends ExchangeProvider { if (curFrom == null || curTo == null) return []; final pairId = curFrom + '_' + curTo; final uri = Uri.https(_apiAuthority, '$_apiPath$_pairsPath/$pairId$_ratePath'); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri, headers: _headers); if (response.statusCode != 200) return []; return json.decode(response.body) as List; } catch (e) { @@ -206,12 +205,7 @@ class XOSwapExchangeProvider extends ExchangeProvider { 'pairId': pairId, }; - final response = await ProxyWrapper().post( - clearnetUri: uri, - headers: _headers, - body: json.encode(payload), - ); - + final response = await http.post(uri, headers: _headers, body: json.encode(payload)); if (response.statusCode != 201) { final responseJSON = json.decode(response.body) as Map; final error = responseJSON['error'] ?? 'Unknown error'; @@ -260,8 +254,7 @@ class XOSwapExchangeProvider extends ExchangeProvider { Future findTradeById({required String id}) async { try { final uri = Uri.https(_apiAuthority, '$_apiPath$_orders/$id'); - final response = await ProxyWrapper().get(clearnetUri: uri); - + final response = await http.get(uri, headers: _headers); if (response.statusCode != 200) { final responseJSON = json.decode(response.body) as Map; if (responseJSON.containsKey('code') && responseJSON['code'] == 'NOT_FOUND') { diff --git a/lib/main.dart b/lib/main.dart index 709304939..43b5951df 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,12 +25,9 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/root/root.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/authentication_store.dart'; -import 'package:cake_wallet/themes/core/material_base_theme.dart'; -import 'package:cake_wallet/themes/utils/theme_provider.dart'; -import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; -import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/view_model/link_view_model.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/address_info.dart'; @@ -41,8 +38,6 @@ import 'package:cw_core/node.dart'; import 'package:cw_core/payjoin_session.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_logger/memory_proxy_logger.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; @@ -55,7 +50,6 @@ import 'package:cw_core/root_dir.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cw_core/window_size.dart'; import 'package:logging/logging.dart'; -import 'package:cake_wallet/core/trade_monitor.dart'; final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); @@ -92,9 +86,6 @@ Future runAppWithZone({Key? topLevelKey}) async { ledgerFile.writeAsStringSync("$content\n${event.message}"); }); } - if (FeatureFlag.hasDevOptions) { - ProxyWrapper.logger = MemoryProxyLogger(); - } runApp(App(key: topLevelKey)); isAppRunning = true; @@ -202,8 +193,8 @@ Future initializeAppConfigs({bool loadWallet = true}) async { final powNodes = await CakeHive.openBox(Node.boxName + "pow"); // must be different from Node.boxName final transactionDescriptions = await CakeHive.openBox( - TransactionDescription.boxName, - encryptionKey: transactionDescriptionsBoxKey); + TransactionDescription.boxName, + encryptionKey: transactionDescriptionsBoxKey); final trades = await CakeHive.openBox(Trade.boxName, encryptionKey: tradesBoxKey); final orders = await CakeHive.openBox(Order.boxName, encryptionKey: ordersBoxKey); final walletInfoSource = await CakeHive.openBox(WalletInfo.boxName); @@ -215,7 +206,8 @@ Future initializeAppConfigs({bool loadWallet = true}) async { final havenSeedStoreBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: HavenSeedStore.boxKey); - final havenSeedStore = await CakeHive.openBox(HavenSeedStore.boxName, + final havenSeedStore = await CakeHive.openBox( + HavenSeedStore.boxName, encryptionKey: havenSeedStoreBoxKey); await initialSetup( @@ -240,26 +232,25 @@ Future initializeAppConfigs({bool loadWallet = true}) async { ); } -Future initialSetup({ - required bool loadWallet, - required SharedPreferences sharedPreferences, - required Box nodes, - required Box powNodes, - required Box walletInfoSource, - required Box contactSource, - required Box tradesSource, - required Box ordersSource, - // required FiatConvertationService fiatConvertationService, - required Box