From 39d3499d07682dd0b3446040807af448cdfb8ec3 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 6 Sep 2023 16:05:26 -0300 Subject: [PATCH 1/3] Merge remote-tracking branch 'origin/linux/password-direct-input' into cw-linux --- .gitignore | 2 + .metadata | 3 + build-guide-linux.md | 195 ++++++++++++ com.cakewallet.CakeWallet.yml | 35 +++ cw_bitcoin/lib/bitcoin_wallet.dart | 11 +- .../bitcoin_wallet_creation_credentials.dart | 4 +- cw_bitcoin/lib/bitcoin_wallet_service.dart | 54 ++-- .../lib/electrum_transaction_history.dart | 10 +- cw_bitcoin/lib/electrum_wallet.dart | 30 +- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 6 +- cw_bitcoin/lib/encryption_file_utils.dart | 42 +++ cw_bitcoin/lib/file.dart | 1 + cw_bitcoin/lib/litecoin_wallet.dart | 9 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 48 +-- cw_bitcoin/pubspec.lock | 85 +++-- cw_bitcoin/pubspec.yaml | 5 + cw_core/lib/cake_hive.dart | 4 - cw_core/lib/erc20_token.dart | 3 +- cw_core/lib/hive_type_ids.dart | 13 - cw_core/lib/node.dart | 3 +- cw_core/lib/pathForWallet.dart | 5 +- cw_core/lib/root_dir.dart | 26 ++ cw_core/lib/sec_random_native.dart | 11 +- cw_core/lib/unspent_coins_info.dart | 5 +- cw_core/lib/wallet_base.dart | 2 + cw_core/lib/wallet_info.dart | 8 +- cw_core/lib/wallet_type.dart | 4 +- cw_core/pubspec.lock | 293 +++++++----------- cw_ethereum/lib/encryption_file_utils.dart | 42 +++ .../lib/ethereum_transaction_history.dart | 14 +- cw_ethereum/lib/ethereum_wallet.dart | 27 +- .../ethereum_wallet_creation_credentials.dart | 4 +- cw_ethereum/lib/ethereum_wallet_service.dart | 17 +- cw_ethereum/pubspec.yaml | 5 + cw_monero/.metadata | 3 + cw_monero/example/linux/.gitignore | 1 + cw_monero/example/linux/CMakeLists.txt | 138 +++++++++ .../example/linux/flutter/CMakeLists.txt | 88 ++++++ .../flutter/generated_plugin_registrant.cc | 15 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 24 ++ cw_monero/example/linux/main.cc | 6 + cw_monero/example/linux/my_application.cc | 104 +++++++ cw_monero/example/linux/my_application.h | 18 ++ cw_monero/ios/Classes/monero_api.cpp | 75 ++++- cw_monero/lib/api/monero_api.dart | 2 +- cw_monero/lib/monero_subaddress_list.dart | 2 +- cw_monero/lib/monero_wallet.dart | 14 +- cw_monero/lib/monero_wallet_service.dart | 18 +- cw_monero/linux/CMakeLists.txt | 270 ++++++++++++++++ cw_monero/linux/cw_monero_plugin.cc | 70 +++++ .../include/cw_monero/cw_monero_plugin.h | 26 ++ cw_monero/macos/Classes/monero_api.cpp | 5 +- cw_monero/pubspec.yaml | 3 +- ios/Podfile | 1 - ios/Runner.xcodeproj/project.pbxproj | 60 ++-- lib/anonpay/anonpay_invoice_info.dart | 3 +- lib/bitcoin/cw_bitcoin.dart | 13 +- lib/buy/moonpay/moonpay_buy_provider.dart | 91 +++--- lib/buy/order.dart | 7 +- lib/core/auth_service.dart | 10 +- lib/core/backup_service.dart | 32 +- lib/core/key_service.dart | 4 +- lib/core/wallet_creation_service.dart | 36 ++- lib/core/wallet_loading_service.dart | 26 +- lib/di.dart | 107 +++++-- lib/entities/contact.dart | 9 +- lib/entities/default_settings_migration.dart | 6 +- lib/entities/fs_migration.dart | 17 +- lib/entities/get_encryption_key.dart | 21 +- lib/entities/language_service.dart | 4 +- lib/entities/load_current_wallet.dart | 7 +- lib/entities/template.dart | 3 +- lib/entities/transaction_description.dart | 3 +- lib/ethereum/cw_ethereum.dart | 7 +- .../changenow_exchange_provider.dart | 8 +- lib/exchange/exchange_template.dart | 3 +- .../sideshift_exchange_provider.dart | 192 +++++------- lib/exchange/trade.dart | 5 +- lib/ionia/ionia_service.dart | 4 +- lib/main.dart | 94 +++--- lib/reactions/check_connection.dart | 3 +- .../on_authentication_state_change.dart | 3 +- .../on_wallet_sync_status_change.dart | 14 +- lib/router.dart | 85 +++-- lib/routes.dart | 2 + lib/src/screens/auth/auth_page.dart | 15 +- lib/src/screens/buy/payfura_page.dart | 58 ++++ .../desktop_action_button.dart | 78 ++--- .../desktop_wallet_selection_dropdown.dart | 20 +- .../dashboard/widgets/address_page.dart | 10 +- .../dashboard/widgets/balance_page.dart | 3 + .../dashboard/widgets/market_place_page.dart | 2 +- .../dashboard/widgets/transactions_page.dart | 58 ++-- .../ionia/auth/ionia_welcome_page.dart | 14 +- .../screens/new_wallet/new_wallet_page.dart | 72 ++++- .../receive/widgets/currency_input_field.dart | 8 +- .../screens/restore/restore_options_page.dart | 2 + .../wallet_restore_from_keys_form.dart | 49 ++- .../wallet_restore_from_seed_form.dart | 52 +++- .../screens/restore/wallet_restore_page.dart | 12 +- .../restore/widgets/restore_button.dart | 10 +- lib/src/screens/root/root.dart | 1 + lib/src/screens/send/send_page.dart | 116 ++++--- .../settings/display_settings_page.dart | 22 +- .../settings/security_backup_page.dart | 63 ++-- .../setup_2fa/setup_2fa_enter_code_page.dart | 2 +- .../support_chat/support_chat_page.dart | 4 +- .../support_chat/widgets/chatwoot_widget.dart | 4 +- lib/src/screens/wallet/wallet_edit_page.dart | 37 ++- .../screens/wallet_list/wallet_list_page.dart | 17 + .../wallet_unlock_arguments.dart | 17 + .../wallet_unlock/wallet_unlock_page.dart | 228 ++++++++++++++ lib/src/widgets/address_text_field.dart | 5 +- lib/src/widgets/base_text_form_field.dart | 5 +- lib/store/app_store.dart | 2 - lib/store/secret_store.dart | 4 +- lib/store/settings_store.dart | 14 +- lib/store/yat/yat_store.dart | 4 +- lib/utils/distribution_info.dart | 2 +- lib/utils/exception_handler.dart | 7 +- lib/view_model/backup_view_model.dart | 9 +- .../dashboard/dashboard_view_model.dart | 3 +- .../dashboard/transaction_list_item.dart | 3 +- .../edit_backup_password_view_model.dart | 4 +- .../exchange/exchange_trade_view_model.dart | 9 +- .../ionia_gift_cards_list_view_model.dart | 11 +- .../settings/other_settings_view_model.dart | 2 +- lib/view_model/support_view_model.dart | 16 +- lib/view_model/trade_details_view_model.dart | 15 +- lib/view_model/wallet_creation_vm.dart | 18 ++ .../wallet_list/wallet_edit_view_model.dart | 9 +- lib/view_model/wallet_new_vm.dart | 10 +- lib/view_model/wallet_restore_view_model.dart | 2 +- .../wallet_unlock_loadable_view_model.dart | 65 ++++ .../wallet_unlock_verifiable_view_model.dart | 61 ++++ lib/view_model/wallet_unlock_view_model.dart | 11 + linux/.gitignore | 1 + linux/CMakeLists.txt | 138 +++++++++ linux/com.cakewallet.CakeWallet.desktop | 9 + linux/flutter/CMakeLists.txt | 88 ++++++ linux/flutter/generated_plugin_registrant.cc | 27 ++ linux/flutter/generated_plugin_registrant.h | 15 + linux/flutter/generated_plugins.cmake | 27 ++ linux/main.cc | 6 + linux/my_application.cc | 104 +++++++ linux/my_application.h | 18 ++ macos/CakeWallet/decrypt.swift | 16 + macos/Flutter/GeneratedPluginRegistrant.swift | 8 +- macos/Podfile | 4 - macos/Runner.xcodeproj/project.pbxproj | 2 + model_generator.sh | 2 + pubspec_base.yaml | 15 +- res/values/strings_ar.arb | 10 +- res/values/strings_bg.arb | 11 +- res/values/strings_cs.arb | 10 +- res/values/strings_de.arb | 12 +- res/values/strings_en.arb | 10 +- res/values/strings_es.arb | 10 +- res/values/strings_fr.arb | 10 +- res/values/strings_ha.arb | 10 +- res/values/strings_hi.arb | 10 +- res/values/strings_hr.arb | 10 +- res/values/strings_id.arb | 10 +- res/values/strings_it.arb | 10 +- res/values/strings_ja.arb | 10 +- res/values/strings_ko.arb | 10 +- res/values/strings_my.arb | 10 +- res/values/strings_nl.arb | 10 +- res/values/strings_pl.arb | 10 +- res/values/strings_pt.arb | 10 +- res/values/strings_ru.arb | 10 +- res/values/strings_th.arb | 10 +- res/values/strings_tr.arb | 10 +- res/values/strings_uk.arb | 10 +- res/values/strings_ur.arb | 10 +- res/values/strings_yo.arb | 10 +- res/values/strings_zh.arb | 10 +- scripts/linux/app_config.sh | 25 ++ scripts/linux/app_env.sh | 35 +++ scripts/linux/build_all.sh | 3 + scripts/linux/build_boost.sh | 36 +++ scripts/linux/build_expat.sh | 20 ++ scripts/linux/build_iconv.sh | 22 ++ scripts/linux/build_monero.sh | 43 +++ scripts/linux/build_monero_all.sh | 13 + scripts/linux/build_openssl.sh | 19 ++ scripts/linux/build_sodium.sh | 19 ++ scripts/linux/build_unbound.sh | 25 ++ scripts/linux/build_zmq.sh | 17 + scripts/linux/cakewallet.sh | 4 + scripts/linux/config.sh | 13 + scripts/linux/setup.sh | 9 + tool/configure.dart | 108 ++++++- tool/update_secrets.dart | 3 +- 195 files changed, 4103 insertions(+), 1112 deletions(-) create mode 100644 build-guide-linux.md create mode 100644 com.cakewallet.CakeWallet.yml create mode 100644 cw_bitcoin/lib/encryption_file_utils.dart delete mode 100644 cw_core/lib/cake_hive.dart delete mode 100644 cw_core/lib/hive_type_ids.dart create mode 100644 cw_core/lib/root_dir.dart create mode 100644 cw_ethereum/lib/encryption_file_utils.dart create mode 100644 cw_monero/example/linux/.gitignore create mode 100644 cw_monero/example/linux/CMakeLists.txt create mode 100644 cw_monero/example/linux/flutter/CMakeLists.txt create mode 100644 cw_monero/example/linux/flutter/generated_plugin_registrant.cc create mode 100644 cw_monero/example/linux/flutter/generated_plugin_registrant.h create mode 100644 cw_monero/example/linux/flutter/generated_plugins.cmake create mode 100644 cw_monero/example/linux/main.cc create mode 100644 cw_monero/example/linux/my_application.cc create mode 100644 cw_monero/example/linux/my_application.h create mode 100644 cw_monero/linux/CMakeLists.txt create mode 100644 cw_monero/linux/cw_monero_plugin.cc create mode 100644 cw_monero/linux/include/cw_monero/cw_monero_plugin.h create mode 100644 lib/src/screens/buy/payfura_page.dart create mode 100644 lib/src/screens/wallet_unlock/wallet_unlock_arguments.dart create mode 100644 lib/src/screens/wallet_unlock/wallet_unlock_page.dart create mode 100644 lib/view_model/wallet_unlock_loadable_view_model.dart create mode 100644 lib/view_model/wallet_unlock_verifiable_view_model.dart create mode 100644 lib/view_model/wallet_unlock_view_model.dart create mode 100644 linux/.gitignore create mode 100644 linux/CMakeLists.txt create mode 100644 linux/com.cakewallet.CakeWallet.desktop create mode 100644 linux/flutter/CMakeLists.txt create mode 100644 linux/flutter/generated_plugin_registrant.cc create mode 100644 linux/flutter/generated_plugin_registrant.h create mode 100644 linux/flutter/generated_plugins.cmake create mode 100644 linux/main.cc create mode 100644 linux/my_application.cc create mode 100644 linux/my_application.h create mode 100644 macos/CakeWallet/decrypt.swift mode change 100644 => 100755 model_generator.sh create mode 100755 scripts/linux/app_config.sh create mode 100755 scripts/linux/app_env.sh create mode 100755 scripts/linux/build_all.sh create mode 100755 scripts/linux/build_boost.sh create mode 100755 scripts/linux/build_expat.sh create mode 100755 scripts/linux/build_iconv.sh create mode 100755 scripts/linux/build_monero.sh create mode 100755 scripts/linux/build_monero_all.sh create mode 100755 scripts/linux/build_openssl.sh create mode 100755 scripts/linux/build_sodium.sh create mode 100755 scripts/linux/build_unbound.sh create mode 100755 scripts/linux/build_zmq.sh create mode 100755 scripts/linux/cakewallet.sh create mode 100755 scripts/linux/config.sh create mode 100755 scripts/linux/setup.sh diff --git a/.gitignore b/.gitignore index 09583004b..0f7098cd4 100644 --- a/.gitignore +++ b/.gitignore @@ -144,3 +144,5 @@ assets/images/app_logo.png macos/Runner/Info.plist macos/Runner/DebugProfile.entitlements macos/Runner/Release.entitlements + +lib/core/secure_storage.dart diff --git a/.metadata b/.metadata index cdddb9350..d25ddea79 100644 --- a/.metadata +++ b/.metadata @@ -18,6 +18,9 @@ migration: - platform: macos create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + - platform: linux + create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 # User provided section diff --git a/build-guide-linux.md b/build-guide-linux.md new file mode 100644 index 000000000..c08d0405b --- /dev/null +++ b/build-guide-linux.md @@ -0,0 +1,195 @@ +# Building CakeWallet for Linux + +## Requirements and Setup + +The following are the system requirements to build CakeWallet for your Linux device. + +``` +Ubuntu >= 16.04 +Flutter 3 or above +``` + +## Building CakeWallet on Linux + +These steps will help you configure and execute a build of CakeWallet from its source code. + +### 1. Installing Package Dependencies + +CakeWallet requires some packages to be install on your build system. You may easily install them on your build system with the following command: + +`$ sudo apt install build-essential cmake pkg-config git curl autoconf libtool` + +> ### Check gcc version +> Need to use gcc 10 or 9 for successfully link dependecnies with flutter.\ +> Check what gcc version is using:\ +> ``` +> $ gcc --version +> $ g++ --version +> ``` +> If you are using gcc version newer than 10, then need to downgrade to version 10.4.0.\ +> ``` +> $ sudo apt install gcc-10 g++-10 +> $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 +> $ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10 +> ``` + +### 2. Installing Flutter + +Need to install flutter. For this please check section [How to install flutter on Linux](https://docs.flutter.dev/get-started/install/linux). + + + + +### 3. Verify Installations + +Verify that the Flutter have been correctly installed on your system with the following command: + +`$ flutter doctor` + +The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding. +``` +Doctor summary (to see all details, run flutter doctor -v): +[✓] Flutter (Channel stable, 3.7.x, on Linux, locale en_US.UTF-8) +``` + +### 4. Acquiring the CakeWallet Source Code + +Download CakeWallet source code + +`$ git clone https://github.com/cake-tech/cake_wallet.git --branch linux/password-direct-input` + +Proceed into the source code before proceeding with the next steps: + +`$ cd cake_wallet/scripts/linux/` + +To configure some project properties run: + +`$ ./cakewallet.sh` + +Build the Monero libraries and their dependencies: + +`$ ./build_all.sh` + +Now the dependencies need to be copied into the CakeWallet project with this command: + +`$ ./setup.sh` + +It is now time to change back to the base directory of the CakeWallet source code: + +`$ cd ../../` + +Install Flutter package dependencies with this command: + +`$ flutter pub get` + + + +> #### If you will get an error like: +> ``` +> The plugin `cw_shared_external` requires your app to be migrated to the Android embedding v2. Follow the steps on the migration doc above and re-run +> this command. +> ``` +> Then need to config Android project settings. For this open `scripts/android` (`$ cd scripts/android`) directory and run followed commands: +> ``` +> $ source ./app_env.sh cakewallet +> $ ./app_config.sh +> $ cd ../.. +> ``` +> Then re-configure Linux project again. For this open `scripts/linux` (`$cd scripts/linux`) directory and run: +> `$ ./cakewallet.sh` +> and back to project root directory: +> `$ cd ../..` +> and fetch dependecies again +> `$ flutter pub get` + + +> ### If you get the error like: +> ``` +> The lower bound of "sdk: '>=2.0.0-dev.68.0 <3.0.0'" must be 2.12.0 or higher to enable null safety. +> ``` +> +> #### Downgrade Flutter to version 3.7.x +> Make sure that Flutter is reverted back to version 3.7.x (which would automatically revert Dart to 2.18 or 2.19) +> +> In your Linux terminal, find where your Flutter SDK is installed with: +> +> ``` +> $ which flutter +> ``` +> +> Proceed to the Flutter SDK path: +> +> ``` +> $ cd user/snap/flutter/common/flutter +> ``` +> +> In the Flutter SDK directory, revert to a 3.7.x version (I used 3.7.12): +> +> +> ``` +> $ git checkout 3.7.12 +> ``` +> Then re-configure Cake Wallet's Linux project again. For this open `scripts/linux` (`$cd scripts/linux`) directory and run: +> `$ ./cakewallet.sh` +> and back to project root directory: +> `$ cd ../..` +> and fetch dependecies again +> `$ flutter pub get` + +Your CakeWallet binary will be built with some specific keys for iterate with 3rd party services. You may generate these secret keys placeholders with the following command: + +`$ flutter packages pub run tool/generate_new_secrets.dart` + +We will generate mobx models for the project. + +`$ ./model_generator.sh` + +Then we need to generate localization files. + +`$ flutter packages pub run tool/generate_localization.dart` + +### 5. Build! + +`$ flutter build linux --release` + +Path to executable file will be: + +`build/linux/x64/release/bundle/cake_wallet` + +> ### Troubleshooting +> +> If you got an error while building the application with `$ flutter build linux --release` command, add `-v` argument to the command (`$ flutter build linux -v --release`) to get details.\ +> If you got in flutter build logs: undefined reference to `hid_free_enumeration`, or another error with undefined reference to `hid_*`, then rebuild monero lib without hidapi lib. Check does exists `libhidapi-dev` in your scope and remove it from your scope for build without it. + +# Flatpak + +For package the built application into flatpak you need fistly to install `flatpak` and `flatpak-builder`: + +`$ sudo apt install flatpak flatpak-builder` + +Then need to [add flathub](https://flatpak.org/setup/Ubuntu) (or just `$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo`). Then need to install freedesktop runtime and sdk: + +`$ flatpak install flathub org.freedesktop.Platform//22.08 org.freedesktop.Sdk//22.08` + +To build with using of `flatpak-build` directory run next: + +`$ flatpak-builder --force-clean flatpak-build com.cakewallet.CakeWallet.yml` + +And then export bundle: + +`$ flatpak build-export export flatpak-build` + +`$ flatpak build-bundle export cake_wallet.flatpak com.cakewallet.CakeWallet` + + +Result file: `cake_wallet.flatpak` should be generated in current directory. + +For install generated flatpak file use: + +`$ flatpak --user install cake_wallet.flatpak` + +For run the installed application run: + +`$ flatpak run com.cakewallet.CakeWallet` + +Copyright (c) 2023 Cake Technologies LLC. \ No newline at end of file diff --git a/com.cakewallet.CakeWallet.yml b/com.cakewallet.CakeWallet.yml new file mode 100644 index 000000000..83efa1388 --- /dev/null +++ b/com.cakewallet.CakeWallet.yml @@ -0,0 +1,35 @@ +app-id: com.cakewallet.CakeWallet +runtime: org.freedesktop.Platform +runtime-version: '22.08' +sdk: org.freedesktop.Sdk +command: cake_wallet +separate-locales: false +finish-args: + - --share=ipc + - --socket=fallback-x11 + - --socket=wayland + - --device=dri + - --socket=pulseaudio + - --share=network + - --filesystem=home +modules: + - name: cake_wallet + buildsystem: simple + only-arches: + - x86_64 + build-commands: + - "cp -R bundle /app/cake_wallet" + - "chmod +x /app/cake_wallet/cake_wallet" + - "mkdir -p /app/bin" + - "ln -s /app/cake_wallet/cake_wallet /app/bin/cake_wallet" + - "mkdir -p /app/share/icons/hicolor/scalable/apps" + - "cp cakewallet_icon_180.png /app/share/icons/hicolor/scalable/apps/com.cakewallet.CakeWallet.png" + - "mkdir -p /app/share/applications" + - "cp com.cakewallet.CakeWallet.desktop /app/share/applications" + sources: + - type: dir + path: build/linux/x64/release + - type: file + path: assets/images/cakewallet_icon_180.png + - type: file + path: linux/com.cakewallet.CakeWallet.desktop diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index c4675df1c..3e4601eb3 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -1,4 +1,5 @@ import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; @@ -23,6 +24,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required Uint8List seedBytes, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -36,7 +38,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, - currency: CryptoCurrency.btc) { + currency: CryptoCurrency.btc, + encryptionFileUtils: encryptionFileUtils) { walletAddresses = BitcoinWalletAddresses( walletInfo, electrumClient: electrumClient, @@ -54,6 +57,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -66,6 +70,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { unspentCoinsInfo: unspentCoinsInfo, initialAddresses: initialAddresses, initialBalance: initialBalance, + encryptionFileUtils: encryptionFileUtils, seedBytes: await mnemonicToSeedBytes(mnemonic), initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex); @@ -76,8 +81,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required String password, + required EncryptionFileUtils encryptionFileUtils }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); return BitcoinWallet( mnemonic: snp.mnemonic, password: password, @@ -86,6 +92,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialAddresses: snp.addresses, initialBalance: snp.balance, seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex); } diff --git a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart index 82173b2d2..4c4c7ae23 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart @@ -2,8 +2,8 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; class BitcoinNewWalletCredentials extends WalletCredentials { - BitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo}) - : super(name: name, walletInfo: walletInfo); + BitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password}) + : super(name: name, walletInfo: walletInfo, password: password); } class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials { diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index bfadaf2a3..3cf72b308 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_service.dart'; @@ -12,14 +13,13 @@ import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; -class BitcoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { - BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); +class BitcoinWalletService extends WalletService { + BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; final Box unspentCoinsInfoSource; + final bool isDirect; @override WalletType getType() => WalletType.bitcoin; @@ -30,7 +30,8 @@ class BitcoinWalletService extends WalletService< mnemonic: await generateMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); return wallet; @@ -42,33 +43,37 @@ class BitcoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await BitcoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.init(); return wallet; } @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await BitcoinWalletBase.open( - password: password, - name: currentName, - walletInfo: currentWalletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: currentName, + walletInfo: currentWalletInfo, + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect), + ); await currentWallet.renameWalletFiles(newName); @@ -80,13 +85,11 @@ class BitcoinWalletService extends WalletService< } @override - Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async => throw UnimplementedError(); @override - Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } @@ -95,7 +98,8 @@ class BitcoinWalletService extends WalletService< password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index be039fa36..29001e160 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -1,9 +1,9 @@ import 'dart:convert'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_history.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; part 'electrum_transaction_history.g.dart'; @@ -16,13 +16,14 @@ class ElectrumTransactionHistory = ElectrumTransactionHistoryBase abstract class ElectrumTransactionHistoryBase extends TransactionHistoryBase with Store { ElectrumTransactionHistoryBase( - {required this.walletInfo, required String password}) + {required this.walletInfo, required String password, required this.encryptionFileUtils}) : _password = password, _height = 0 { transactions = ObservableMap(); } final WalletInfo walletInfo; + final EncryptionFileUtils encryptionFileUtils; String _password; int _height; @@ -44,7 +45,7 @@ abstract class ElectrumTransactionHistoryBase final path = '$dirPath/$transactionsHistoryFileName'; final data = json.encode({'height': _height, 'transactions': transactions}); - await writeData(path: path, password: _password, data: data); + await encryptionFileUtils.write(path: path, password: _password, data: data); } catch (e) { print('Error while save bitcoin transaction history: ${e.toString()}'); } @@ -59,7 +60,7 @@ abstract class ElectrumTransactionHistoryBase final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); final path = '$dirPath/$transactionsHistoryFileName'; - final content = await read(path: path, password: _password); + final content = await encryptionFileUtils.read(path: path, password: _password); return json.decode(content) as Map; } @@ -85,5 +86,4 @@ abstract class ElectrumTransactionHistoryBase void _update(ElectrumTransactionInfo transaction) => transactions[transaction.id] = transaction; - } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index f9437e668..27ea925ed 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'dart:typed_data'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; @@ -14,6 +16,7 @@ import 'package:cw_core/pathForWallet.dart'; import 'package:cw_bitcoin/address_to_output_script.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; @@ -21,7 +24,6 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; @@ -48,6 +50,7 @@ abstract class ElectrumWalletBase extends WalletBase? initialAddresses, ElectrumClient? electrumClient, ElectrumBalance? initialBalance, @@ -70,7 +73,10 @@ abstract class ElectrumWalletBase extends WalletBase @@ -78,6 +84,7 @@ abstract class ElectrumWalletBase extends WalletBase unspentCoinsInfo; @@ -107,6 +114,9 @@ abstract class ElectrumWalletBase extends WalletBase mnemonic; + @override + String get password => _password; + bitcoin.NetworkType networkType; @override @@ -119,8 +129,6 @@ abstract class ElectrumWalletBase extends WalletBase?> _scripthashesUpdateSubject; bool _isTransactionUpdating; - void Function(FlutterErrorDetails)? _onError; - Future init() async { await walletAddresses.init(); await transactionHistory.init(); @@ -323,7 +331,7 @@ abstract class ElectrumWalletBase extends WalletBase minAmount) { @@ -427,7 +435,7 @@ abstract class ElectrumWalletBase extends WalletBase save() async { final path = await makePath(); - await write(path: path, password: _password, data: toJSON()); + await encryptionFileUtils.write(path: path, password: _password, data: toJSON()); await transactionHistory.save(); } @@ -665,13 +673,8 @@ abstract class ElectrumWalletBase extends WalletBase _onError = onError; } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 6db0c23f2..61a1e898d 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; -import 'package:cw_bitcoin/file.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_type.dart'; @@ -26,9 +26,9 @@ class ElectrumWallletSnapshot { int regularAddressIndex; int changeAddressIndex; - static Future load(String name, WalletType type, String password) async { + static Future load(EncryptionFileUtils encryptionFileUtils, String name, WalletType type, String password) async { final path = await pathForWallet(name: name, type: type); - final jsonSource = await read(path: path, password: password); + final jsonSource = await encryptionFileUtils.read(path: path, password: password); final data = json.decode(jsonSource) as Map; final addressesTmp = data['addresses'] as List? ?? []; final mnemonic = data['mnemonic'] as String; diff --git a/cw_bitcoin/lib/encryption_file_utils.dart b/cw_bitcoin/lib/encryption_file_utils.dart new file mode 100644 index 000000000..95f000f04 --- /dev/null +++ b/cw_bitcoin/lib/encryption_file_utils.dart @@ -0,0 +1,42 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'package:cw_bitcoin/file.dart' as bf; +import 'package:cake_backup/backup.dart' as cwb; + +EncryptionFileUtils encryptionFileUtilsFor(bool direct) + => direct + ? XChaCha20EncryptionFileUtils() + : Salsa20EncryhptionFileUtils(); + +abstract class EncryptionFileUtils { + Future write({required String path, required String password, required String data}); + Future read({required String path, required String password}); +} + +class Salsa20EncryhptionFileUtils extends EncryptionFileUtils { + // Requires legacy complex key + iv as password + @override + Future write({required String path, required String password, required String data}) async + => await bf.write(path: path, password: password, data: data); + + // Requires legacy complex key + iv as password + @override + Future read({required String path, required String password}) async + => await bf.read(path: path, password: password); +} + +class XChaCha20EncryptionFileUtils extends EncryptionFileUtils { + @override + Future write({required String path, required String password, required String data}) async { + final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits)); + await File(path).writeAsBytes(encrypted); + } + + @override + Future read({required String path, required String password}) async { + final file = File(path); + final encrypted = await file.readAsBytes(); + final bytes = await cwb.decrypt(password, encrypted); + return String.fromCharCodes(bytes); + } +} \ No newline at end of file diff --git a/cw_bitcoin/lib/file.dart b/cw_bitcoin/lib/file.dart index 8fd236ec3..49b7d895e 100644 --- a/cw_bitcoin/lib/file.dart +++ b/cw_bitcoin/lib/file.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_core/key.dart'; import 'package:encrypt/encrypt.dart' as encrypt; +// Do not use directly, move to Salsa20EncryhptionFile Future write( {required String path, required String password, diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 6bf1c5735..6d5171fd7 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -1,5 +1,6 @@ import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_bitcoin/litecoin_wallet_addresses.dart'; @@ -26,6 +27,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required Uint8List seedBytes, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -39,6 +41,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, + encryptionFileUtils: encryptionFileUtils, currency: CryptoCurrency.ltc) { walletAddresses = LitecoinWalletAddresses( walletInfo, @@ -58,6 +61,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -71,6 +75,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: await mnemonicToSeedBytes(mnemonic), + encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex); } @@ -80,8 +85,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required String password, + required EncryptionFileUtils encryptionFileUtils }) async { - final snp = await ElectrumWallletSnapshot.load (name, walletInfo.type, password); + final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); return LitecoinWallet( mnemonic: snp.mnemonic, password: password, @@ -90,6 +96,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialAddresses: snp.addresses, initialBalance: snp.balance, seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex); } diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index b13ac7a7f..1df08d8e0 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; @@ -12,14 +13,13 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:collection/collection.dart'; -class LitecoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { - LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); +class LitecoinWalletService extends WalletService { + LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; final Box unspentCoinsInfoSource; + final bool isDirect; @override WalletType getType() => WalletType.litecoin; @@ -30,7 +30,8 @@ class LitecoinWalletService extends WalletService< mnemonic: await generateMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); @@ -43,33 +44,37 @@ class LitecoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await LitecoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.init(); return wallet; } @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await LitecoinWalletBase.open( - password: password, - name: currentName, - walletInfo: currentWalletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: currentName, + walletInfo: currentWalletInfo, + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect), + ); await currentWallet.renameWalletFiles(newName); @@ -96,7 +101,8 @@ class LitecoinWalletService extends WalletService< password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index bfcd9e5a6..4bce06bab 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" asn1lib: dependency: transitive description: @@ -111,10 +111,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" build_resolvers: dependency: "direct dev" description: @@ -151,10 +151,19 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: "31b7c748fd4b9adf8d25d72a4c4a59ef119f12876cf414f94f8af5131d5fa2b0" url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.4.4" + cake_backup: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38" + url: "https://github.com/cake-tech/cake_backup.git" + source: git + version: "1.0.0+1" characters: dependency: transitive description: @@ -215,10 +224,18 @@ packages: dependency: "direct main" description: name: cryptography - sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35 url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.5.0" + cupertino_icons: + dependency: transitive + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" cw_core: dependency: "direct main" description: @@ -270,10 +287,10 @@ packages: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.1" flutter: dependency: "direct main" description: flutter @@ -440,10 +457,10 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "6738620307a424d2c9ad8b873f4dce391c44e9135eb4e75668ac8202fec7a9b8" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.1.4" mobx_codegen: dependency: "direct dev" description: @@ -472,50 +489,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.0.13" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.0.24" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "026b97a6c29da75181a37aae2eba9227f5fe13cb2838c6b975ce209328b8ab4e" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.3" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.5" platform: dependency: transitive description: @@ -528,10 +545,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pointycastle: dependency: transitive description: @@ -568,10 +585,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + sha256: ec85d7d55339d85f44ec2b682a82fea340071e8978257e5a43e69f79e98ef50c url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" rxdart: dependency: "direct main" description: @@ -681,6 +698,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" + source: hosted + version: "2.0.1" typed_data: dependency: transitive description: @@ -733,10 +758,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.0" yaml: dependency: transitive description: diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index dae0af39b..e0f5dad67 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -27,6 +27,11 @@ dependencies: unorm_dart: ^0.2.0 cryptography: ^2.0.5 encrypt: ^5.0.1 + cake_backup: + git: + url: https://github.com/cake-tech/cake_backup.git + ref: main + version: 1.0.0 dev_dependencies: flutter_test: diff --git a/cw_core/lib/cake_hive.dart b/cw_core/lib/cake_hive.dart deleted file mode 100644 index aadf6bf9a..000000000 --- a/cw_core/lib/cake_hive.dart +++ /dev/null @@ -1,4 +0,0 @@ -import 'package:hive/hive.dart'; -import 'package:hive/src/hive_impl.dart'; - -final HiveInterface CakeHive = HiveImpl(); diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index fd27aaba6..db5b6db5b 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -1,5 +1,4 @@ import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'erc20_token.g.dart'; @@ -54,7 +53,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { iconPath: icon, ); - static const typeId = ERC20_TOKEN_TYPE_ID; + static const typeId = 12; static const boxName = 'Erc20Tokens'; @override diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart deleted file mode 100644 index 0961182bc..000000000 --- a/cw_core/lib/hive_type_ids.dart +++ /dev/null @@ -1,13 +0,0 @@ -const CONTACT_TYPE_ID = 0; -const NODE_TYPE_ID = 1; -const TRANSACTION_TYPE_ID = 2; -const TRADE_TYPE_ID = 3; -const WALLET_INFO_TYPE_ID = 4; -const WALLET_TYPE_TYPE_ID = 5; -const TEMPLATE_TYPE_ID = 6; -const EXCHANGE_TEMPLATE_TYPE_ID = 7; -const ORDER_TYPE_ID = 8; -const UNSPENT_COINS_INFO_TYPE_ID = 9; -const ANONPAY_INVOICE_INFO_TYPE_ID = 10; - -const ERC20_TOKEN_TYPE_ID = 12; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 59a1450f6..3fa45b44c 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -3,7 +3,6 @@ import 'package:cw_core/keyable.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; @@ -38,7 +37,7 @@ class Node extends HiveObject with Keyable { trusted = map['trusted'] as bool? ?? false, socksProxyAddress = map['socksProxyPort'] as String?; - static const typeId = NODE_TYPE_ID; + static const typeId = 1; static const boxName = 'Nodes'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/pathForWallet.dart b/cw_core/lib/pathForWallet.dart index af4838ffa..5b27a4729 100644 --- a/cw_core/lib/pathForWallet.dart +++ b/cw_core/lib/pathForWallet.dart @@ -1,10 +1,11 @@ import 'dart:io'; +import 'package:cw_core/root_dir.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:path_provider/path_provider.dart'; Future pathForWalletDir({required String name, required WalletType type}) async { - final root = await getApplicationDocumentsDirectory(); + final root = await getAppDir(); final prefix = walletTypeToString(type).toLowerCase(); final walletsDir = Directory('${root.path}/wallets'); final walletDire = Directory('${walletsDir.path}/$prefix/$name'); @@ -21,7 +22,7 @@ Future pathForWallet({required String name, required WalletType type}) a .then((path) => path + '/$name'); Future outdatedAndroidPathForWalletDir({required String name}) async { - final directory = await getApplicationDocumentsDirectory(); + final directory = await getAppDir(); final pathDir = directory.path + '/$name'; return pathDir; diff --git a/cw_core/lib/root_dir.dart b/cw_core/lib/root_dir.dart new file mode 100644 index 000000000..efbe59ce9 --- /dev/null +++ b/cw_core/lib/root_dir.dart @@ -0,0 +1,26 @@ +import 'dart:io'; +import 'package:path_provider/path_provider.dart'; + +String? _rootDirPath; + +void setRootDirFromEnv() + => _rootDirPath = Platform.environment['CAKE_WALLET_DIR']; + +Future getAppDir({String appName = 'cake_wallet'}) async { + Directory dir; + + if (_rootDirPath != null && _rootDirPath!.isNotEmpty) { + dir = Directory.fromUri(Uri.file(_rootDirPath!)); + dir.create(recursive: true); + } else { + dir = await getApplicationDocumentsDirectory(); + + if (Platform.isLinux) { + final appDirPath = '${dir.path}/$appName'; + dir = Directory.fromUri(Uri.file(appDirPath)); + await dir.create(recursive: true); + } + } + + return dir; +} \ No newline at end of file diff --git a/cw_core/lib/sec_random_native.dart b/cw_core/lib/sec_random_native.dart index ce251efc0..02230b872 100644 --- a/cw_core/lib/sec_random_native.dart +++ b/cw_core/lib/sec_random_native.dart @@ -1,11 +1,18 @@ -import 'dart:typed_data'; - +import 'dart:io'; +import 'dart:math'; import 'package:flutter/services.dart'; const utils = const MethodChannel('com.cake_wallet/native_utils'); Future secRandom(int count) async { try { + if (Platform.isLinux) { + // Used method to get securely generated random bytes from cake backups + const byteSize = 256; + final rng = Random.secure(); + return Uint8List.fromList(List.generate(count, (_) => rng.nextInt(byteSize))); + } + return await utils.invokeMethod('sec_random', {'count': count}) ?? Uint8List.fromList([]); } on PlatformException catch (_) { return Uint8List.fromList([]); diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 68bbcbfd2..6fd682c06 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'unspent_coins_info.g.dart'; @@ -17,7 +16,7 @@ class UnspentCoinsInfo extends HiveObject { this.keyImage = null }); - static const typeId = UNSPENT_COINS_INFO_TYPE_ID; + static const typeId = 9; static const boxName = 'Unspent'; static const boxKey = 'unspentBoxKey'; @@ -51,4 +50,4 @@ class UnspentCoinsInfo extends HiveObject { String get note => noteRaw ?? ''; set note(String value) => noteRaw = value; -} +} \ No newline at end of file diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 5bc5ef914..3f6b57edc 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -74,6 +74,8 @@ abstract class WalletBase< Future changePassword(String password); + String get password; + Future? updateBalance(); void setExceptionHandler(void Function(FlutterErrorDetails) onError) => null; diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 6b3fa9e98..a25702cf7 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,7 +1,7 @@ -import 'dart:async'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'dart:async'; part 'wallet_info.g.dart'; @@ -30,7 +30,7 @@ class WalletInfo extends HiveObject { yatEid, yatLastUsedAddressRaw, showIntroCakePayCard); } - static const typeId = WALLET_INFO_TYPE_ID; + static const typeId = 4; static const boxName = 'WalletInfo'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 62c2ad410..a65839041 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -1,5 +1,4 @@ import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'wallet_type.g.dart'; @@ -11,8 +10,9 @@ const walletTypes = [ WalletType.haven, WalletType.ethereum, ]; +const walletTypeTypeId = 5; -@HiveType(typeId: WALLET_TYPE_TYPE_ID) +@HiveType(typeId: walletTypeTypeId) enum WalletType { @HiveField(0) monero, diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 01e19dda4..b0fb67435 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -5,218 +5,191 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.7.0" args: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.3.2" + version: "2.4.0" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.4.0" async: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.10.0" + version: "2.9.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" build: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" build_resolvers: dependency: "direct dev" description: name: build_resolvers - sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "8.4.3" + version: "8.4.4" characters: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.1" checked_yaml: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.2" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.4.0" collection: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.17.0" + version: "1.16.0" convert: dependency: transitive description: name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.1" crypto: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.0.2" dart_style: dependency: transitive description: name: dart_style - sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.4" encrypt: dependency: "direct main" description: name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "5.0.1" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.1" file: dependency: "direct main" description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "6.1.4" fixnum: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.0.1" flutter: dependency: "direct main" description: flutter @@ -226,8 +199,7 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.0.6+5" flutter_test: @@ -239,288 +211,252 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.2.0" glob: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" graphs: dependency: transitive description: name: graphs - sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.0" hive: dependency: transitive description: name: hive - sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.2.3" hive_generator: dependency: "direct dev" description: name: hive_generator - sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.3" http: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.0.2" intl: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "0.6.5" json_annotation: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.8.0" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.1.1" matcher: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.12.13" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.1.5" meta: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.8.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" mobx: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.3+1" + version: "2.1.4" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.1" package_config: dependency: transitive description: name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" path: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.8.2" path_provider: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.12" + version: "2.0.13" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.22" + version: "2.0.24" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.7" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.5" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.6.2" pool: dependency: transitive description: name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.5.1" process: dependency: transitive description: name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.2.2" shelf: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.4.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.3" sky_engine: @@ -532,136 +468,119 @@ packages: dependency: transitive description: name: source_gen - sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.3" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.9.1" + version: "1.9.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.11.0" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" stream_transform: dependency: transitive description: name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.4.16" + version: "0.4.12" timing: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" typed_data: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.2" watcher: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.3.0" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.3" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.2.0+3" + version: "1.0.0" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "3.1.1" sdks: diff --git a/cw_ethereum/lib/encryption_file_utils.dart b/cw_ethereum/lib/encryption_file_utils.dart new file mode 100644 index 000000000..4644b8cfb --- /dev/null +++ b/cw_ethereum/lib/encryption_file_utils.dart @@ -0,0 +1,42 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'package:cw_ethereum/file.dart' as ef; +import 'package:cake_backup/backup.dart' as cwb; + +EncryptionFileUtils encryptionFileUtilsFor(bool direct) + => direct + ? XChaCha20EncryptionFileUtils() + : Salsa20EncryhptionFileUtils(); + +abstract class EncryptionFileUtils { + Future write({required String path, required String password, required String data}); + Future read({required String path, required String password}); +} + +class Salsa20EncryhptionFileUtils extends EncryptionFileUtils { + // Requires legacy complex key + iv as password + @override + Future write({required String path, required String password, required String data}) async + => await ef.write(path: path, password: password, data: data); + + // Requires legacy complex key + iv as password + @override + Future read({required String path, required String password}) async + => await ef.read(path: path, password: password); +} + +class XChaCha20EncryptionFileUtils extends EncryptionFileUtils { + @override + Future write({required String path, required String password, required String data}) async { + final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits)); + await File(path).writeAsBytes(encrypted); + } + + @override + Future read({required String path, required String password}) async { + final file = File(path); + final encrypted = await file.readAsBytes(); + final bytes = await cwb.decrypt(password, encrypted); + return String.fromCharCodes(bytes); + } +} \ No newline at end of file diff --git a/cw_ethereum/lib/ethereum_transaction_history.dart b/cw_ethereum/lib/ethereum_transaction_history.dart index 4511f4436..397625f05 100644 --- a/cw_ethereum/lib/ethereum_transaction_history.dart +++ b/cw_ethereum/lib/ethereum_transaction_history.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:cw_ethereum/file.dart'; +import 'package:cw_ethereum/encryption_file_utils.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_ethereum/ethereum_transaction_info.dart'; @@ -15,12 +15,16 @@ class EthereumTransactionHistory = EthereumTransactionHistoryBase with _$Ethereu abstract class EthereumTransactionHistoryBase extends TransactionHistoryBase with Store { - EthereumTransactionHistoryBase({required this.walletInfo, required String password}) - : _password = password { + EthereumTransactionHistoryBase({ + required this.walletInfo, + required String password, + required this.encryptionFileUtils, + }) : _password = password { transactions = ObservableMap(); } final WalletInfo walletInfo; + final EncryptionFileUtils encryptionFileUtils; String _password; Future init() async => await _load(); @@ -31,7 +35,7 @@ abstract class EthereumTransactionHistoryBase final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); final path = '$dirPath/$transactionsHistoryFileName'; final data = json.encode({'transactions': transactions}); - await writeData(path: path, password: _password, data: data); + await encryptionFileUtils.write(path: path, password: _password, data: data); } catch (e, s) { print('Error while save ethereum transaction history: ${e.toString()}'); print(s); @@ -48,7 +52,7 @@ abstract class EthereumTransactionHistoryBase Future> _read() async { final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); final path = '$dirPath/$transactionsHistoryFileName'; - final content = await read(path: path, password: _password); + final content = await encryptionFileUtils.read(path: path, password: _password); if (content.isEmpty) { return {}; } diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 8d7c477e1..d8c236657 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'dart:math'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pending_transaction.dart'; @@ -15,6 +14,7 @@ import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_ethereum/default_erc20_tokens.dart'; +import 'package:cw_ethereum/encryption_file_utils.dart'; import 'package:cw_ethereum/erc20_balance.dart'; import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_ethereum/ethereum_exceptions.dart'; @@ -47,22 +47,28 @@ abstract class EthereumWalletBase String? mnemonic, String? privateKey, required String password, + required EncryptionFileUtils encryptionFileUtils, ERC20Balance? initialBalance, }) : syncStatus = NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, _hexPrivateKey = privateKey, _isTransactionUpdating = false, + _encryptionFileUtils = encryptionFileUtils, _client = EthereumClient(), walletAddresses = EthereumWalletAddresses(walletInfo), balance = ObservableMap.of( {CryptoCurrency.eth: initialBalance ?? ERC20Balance(BigInt.zero)}), super(walletInfo) { this.walletInfo = walletInfo; - transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password); + transactionHistory = EthereumTransactionHistory( + walletInfo: walletInfo, + password: password, + encryptionFileUtils: encryptionFileUtils, + ); - if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { - CakeHive.registerAdapter(Erc20TokenAdapter()); + if (!Hive.isAdapterRegistered(Erc20Token.typeId)) { + Hive.registerAdapter(Erc20TokenAdapter()); } _sharedPrefs.complete(SharedPreferences.getInstance()); @@ -72,6 +78,8 @@ abstract class EthereumWalletBase final String? _hexPrivateKey; final String _password; + final EncryptionFileUtils _encryptionFileUtils; + late final Box erc20TokensBox; late final EthPrivateKey _ethPrivateKey; @@ -99,7 +107,7 @@ abstract class EthereumWalletBase Completer _sharedPrefs = Completer(); Future init() async { - erc20TokensBox = await CakeHive.openBox(Erc20Token.boxName); + erc20TokensBox = await Hive.openBox(Erc20Token.boxName); await walletAddresses.init(); await transactionHistory.init(); _ethPrivateKey = await getPrivateKey( @@ -301,7 +309,7 @@ abstract class EthereumWalletBase Future save() async { await walletAddresses.updateAddressesInBox(); final path = await makePath(); - await write(path: path, password: _password, data: toJSON()); + await _encryptionFileUtils.write(path: path, password: _password, data: toJSON()); await transactionHistory.save(); } @@ -344,9 +352,10 @@ abstract class EthereumWalletBase required String name, required String password, required WalletInfo walletInfo, + required EncryptionFileUtils encryptionFileUtils, }) async { final path = await pathForWallet(name: name, type: walletInfo.type); - final jsonSource = await read(path: path, password: password); + final jsonSource = await encryptionFileUtils.read(path: path, password: password); final data = json.decode(jsonSource) as Map; final mnemonic = data['mnemonic'] as String?; final privateKey = data['private_key'] as String?; @@ -358,6 +367,7 @@ abstract class EthereumWalletBase mnemonic: mnemonic, privateKey: privateKey, initialBalance: balance, + encryptionFileUtils: encryptionFileUtils, ); } @@ -502,4 +512,7 @@ abstract class EthereumWalletBase _transactionsUpdateTimer?.cancel(); } } + + @override + String get password => _password; } diff --git a/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart b/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart index 6546f2fae..3d1efa54a 100644 --- a/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart +++ b/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart @@ -2,8 +2,8 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; class EthereumNewWalletCredentials extends WalletCredentials { - EthereumNewWalletCredentials({required String name, WalletInfo? walletInfo}) - : super(name: name, walletInfo: walletInfo); + EthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password}) + : super(name: name, walletInfo: walletInfo, password: password); } class EthereumRestoreWalletFromSeedCredentials extends WalletCredentials { diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 16dbc0b04..66066b996 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -5,6 +5,7 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:cw_ethereum/encryption_file_utils.dart'; import 'package:cw_ethereum/ethereum_mnemonics.dart'; import 'package:cw_ethereum/ethereum_wallet.dart'; import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart'; @@ -14,9 +15,10 @@ import 'package:collection/collection.dart'; class EthereumWalletService extends WalletService { - EthereumWalletService(this.walletInfoSource); + EthereumWalletService(this.walletInfoSource, this.isDirect); final Box walletInfoSource; + final bool isDirect; @override Future create(EthereumNewWalletCredentials credentials) async { @@ -25,6 +27,7 @@ class EthereumWalletService extends WalletService remove(String wallet) async { File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @@ -91,6 +95,7 @@ class EthereumWalletService extends WalletService info.id == WalletBase.idFor(currentName, getType())); final currentWallet = await EthereumWalletBase.open( - password: password, name: currentName, walletInfo: currentWalletInfo); + password: password, + name: currentName, + walletInfo: currentWalletInfo, + encryptionFileUtils: encryptionFileUtilsFor(isDirect), + ); await currentWallet.renameWalletFiles(newName); diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 5d19589f3..6b324aa7b 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -23,6 +23,11 @@ dependencies: shared_preferences: ^2.0.15 cw_core: path: ../cw_core + cake_backup: + git: + url: https://github.com/cake-tech/cake_backup.git + ref: main + version: 1.0.0 dev_dependencies: flutter_test: diff --git a/cw_monero/.metadata b/cw_monero/.metadata index 46a2f7f6f..679a0404c 100644 --- a/cw_monero/.metadata +++ b/cw_monero/.metadata @@ -18,6 +18,9 @@ migration: - platform: macos create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + - platform: linux + create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 # User provided section diff --git a/cw_monero/example/linux/.gitignore b/cw_monero/example/linux/.gitignore new file mode 100644 index 000000000..d3896c984 --- /dev/null +++ b/cw_monero/example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/cw_monero/example/linux/CMakeLists.txt b/cw_monero/example/linux/CMakeLists.txt new file mode 100644 index 000000000..8b2f28252 --- /dev/null +++ b/cw_monero/example/linux/CMakeLists.txt @@ -0,0 +1,138 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "cw_monero_example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.cakewallet.cw_monero") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/cw_monero/example/linux/flutter/CMakeLists.txt b/cw_monero/example/linux/flutter/CMakeLists.txt new file mode 100644 index 000000000..d5bd01648 --- /dev/null +++ b/cw_monero/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/cw_monero/example/linux/flutter/generated_plugin_registrant.cc b/cw_monero/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..1936c88a6 --- /dev/null +++ b/cw_monero/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) cw_monero_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "CwMoneroPlugin"); + cw_monero_plugin_register_with_registrar(cw_monero_registrar); +} diff --git a/cw_monero/example/linux/flutter/generated_plugin_registrant.h b/cw_monero/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/cw_monero/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_monero/example/linux/flutter/generated_plugins.cmake b/cw_monero/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..efcc9a8f9 --- /dev/null +++ b/cw_monero/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + cw_monero +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/cw_monero/example/linux/main.cc b/cw_monero/example/linux/main.cc new file mode 100644 index 000000000..e7c5c5437 --- /dev/null +++ b/cw_monero/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/cw_monero/example/linux/my_application.cc b/cw_monero/example/linux/my_application.cc new file mode 100644 index 000000000..875fc557a --- /dev/null +++ b/cw_monero/example/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "cw_monero_example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "cw_monero_example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/cw_monero/example/linux/my_application.h b/cw_monero/example/linux/my_application.h new file mode 100644 index 000000000..72271d5e4 --- /dev/null +++ b/cw_monero/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 66b8605c6..d81907813 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -13,16 +13,22 @@ // Fix for randomx on ios void __clear_cache(void* start, void* end) { } #include "../External/ios/include/wallet2_api.h" +#elif __linux__ +#include "../External/linux/include/wallet2_api.h" +#include #else #include "../External/android/include/wallet2_api.h" #endif +#if defined(__GNUC__) + #define FUNCTION_VISABILITY_ATTRIBUTE __attribute__((visibility("default"))) __attribute__((used)) +#endif + using namespace std::chrono_literals; #ifdef __cplusplus extern "C" { #endif - const uint64_t MONERO_BLOCK_SIZE = 1000; struct Utf8Box { @@ -151,7 +157,8 @@ extern "C" fee = transaction->fee(); blockHeight = transaction->blockHeight(); subaddrAccount = transaction->subaddrAccount(); - std::set::iterator it = transaction->subaddrIndex().begin(); + std::set subIndex = transaction->subaddrIndex(); + std::set::iterator it = subIndex.begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); datetime = static_cast(transaction->timestamp()); @@ -250,6 +257,7 @@ extern "C" std::mutex store_lock; bool is_storing = false; + FUNCTION_VISABILITY_ATTRIBUTE void change_current_wallet(Monero::Wallet *wallet) { m_wallet = wallet; @@ -300,6 +308,7 @@ extern "C" return m_wallet; } + FUNCTION_VISABILITY_ATTRIBUTE bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error) { Monero::NetworkType _networkType = static_cast(networkType); @@ -322,6 +331,7 @@ extern "C" return true; } + FUNCTION_VISABILITY_ATTRIBUTE bool restore_wallet_from_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error) { Monero::NetworkType _networkType = static_cast(networkType); @@ -347,6 +357,7 @@ extern "C" return true; } + FUNCTION_VISABILITY_ATTRIBUTE bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error) { Monero::NetworkType _networkType = static_cast(networkType); @@ -375,6 +386,7 @@ extern "C" return true; } + FUNCTION_VISABILITY_ATTRIBUTE bool load_wallet(char *path, char *password, int32_t nettype) { nice(19); @@ -390,78 +402,91 @@ extern "C" return !(status != Monero::Wallet::Status_Ok || !errorString.empty()); } + FUNCTION_VISABILITY_ATTRIBUTE char *error_string() { return strdup(get_current_wallet()->errorString().c_str()); } - + FUNCTION_VISABILITY_ATTRIBUTE bool is_wallet_exist(char *path) { return Monero::WalletManagerFactory::getWalletManager()->walletExists(std::string(path)); } + FUNCTION_VISABILITY_ATTRIBUTE void close_current_wallet() { Monero::WalletManagerFactory::getWalletManager()->closeWallet(get_current_wallet()); change_current_wallet(nullptr); } + FUNCTION_VISABILITY_ATTRIBUTE char *get_filename() { return strdup(get_current_wallet()->filename().c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE char *secret_view_key() { return strdup(get_current_wallet()->secretViewKey().c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE char *public_view_key() { return strdup(get_current_wallet()->publicViewKey().c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE char *secret_spend_key() { return strdup(get_current_wallet()->secretSpendKey().c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE char *public_spend_key() { return strdup(get_current_wallet()->publicSpendKey().c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE char *get_address(uint32_t account_index, uint32_t address_index) { return strdup(get_current_wallet()->address(account_index, address_index).c_str()); } - + FUNCTION_VISABILITY_ATTRIBUTE const char *seed() { return strdup(get_current_wallet()->seed().c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t get_full_balance(uint32_t account_index) { return get_current_wallet()->balance(account_index); } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t get_unlocked_balance(uint32_t account_index) { return get_current_wallet()->unlockedBalance(account_index); } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t get_current_height() { return get_current_wallet()->blockChainHeight(); } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t get_node_height() { return get_current_wallet()->daemonBlockChainHeight(); } + FUNCTION_VISABILITY_ATTRIBUTE bool connect_to_node(char *error) { nice(19); @@ -475,6 +500,7 @@ extern "C" return is_connected; } + FUNCTION_VISABILITY_ATTRIBUTE bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *socksProxyAddress, char *error) { nice(19); @@ -495,9 +521,9 @@ extern "C" } if (socksProxyAddress != nullptr) - { - _socksProxyAddress = std::string(socksProxyAddress); - } + { + _socksProxyAddress = std::string(socksProxyAddress); + } bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet, _socksProxyAddress); @@ -511,27 +537,32 @@ extern "C" return inited; } + FUNCTION_VISABILITY_ATTRIBUTE bool is_connected() { return get_current_wallet()->connected(); } + FUNCTION_VISABILITY_ATTRIBUTE void start_refresh() { get_current_wallet()->refreshAsync(); get_current_wallet()->startRefresh(); } + FUNCTION_VISABILITY_ATTRIBUTE void set_refresh_from_block_height(uint64_t height) { get_current_wallet()->setRefreshFromBlockHeight(height); } + FUNCTION_VISABILITY_ATTRIBUTE void set_recovering_from_seed(bool is_recovery) { get_current_wallet()->setRecoveringFromSeed(is_recovery); } + FUNCTION_VISABILITY_ATTRIBUTE void store(char *path) { store_lock.lock(); @@ -545,6 +576,7 @@ extern "C" store_lock.unlock(); } + FUNCTION_VISABILITY_ATTRIBUTE bool set_password(char *password, Utf8Box &error) { bool is_changed = get_current_wallet()->setPassword(std::string(password)); @@ -555,6 +587,7 @@ extern "C" return is_changed; } + FUNCTION_VISABILITY_ATTRIBUTE bool transaction_create(char *address, char *payment_id, char *amount, uint8_t priority_raw, uint32_t subaddr_account, char **preferred_inputs, uint32_t preferred_inputs_size, @@ -604,6 +637,7 @@ extern "C" return true; } + FUNCTION_VISABILITY_ATTRIBUTE bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size, uint8_t priority_raw, uint32_t subaddr_account, char **preferred_inputs, uint32_t preferred_inputs_size, @@ -655,6 +689,7 @@ extern "C" return true; } + FUNCTION_VISABILITY_ATTRIBUTE bool transaction_commit(PendingTransactionRaw *transaction, Utf8Box &error) { bool committed = transaction->transaction->commit(); @@ -669,6 +704,7 @@ extern "C" return committed; } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t get_node_height_or_update(uint64_t base_eight) { if (m_cached_syncing_blockchain_height < base_eight) { @@ -678,6 +714,7 @@ extern "C" return m_cached_syncing_blockchain_height; } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t get_syncing_height() { if (m_listener == nullptr) { @@ -698,6 +735,7 @@ extern "C" return height; } + FUNCTION_VISABILITY_ATTRIBUTE uint64_t is_needed_to_refresh() { if (m_listener == nullptr) { @@ -713,6 +751,7 @@ extern "C" return should_refresh; } + FUNCTION_VISABILITY_ATTRIBUTE uint8_t is_new_transaction_exist() { if (m_listener == nullptr) { @@ -729,6 +768,7 @@ extern "C" return is_new_transaction_exist; } + FUNCTION_VISABILITY_ATTRIBUTE void set_listener() { m_last_known_wallet_height = 0; @@ -742,6 +782,7 @@ extern "C" get_current_wallet()->setListener(m_listener); } + FUNCTION_VISABILITY_ATTRIBUTE int64_t *subaddrress_get_all() { std::vector _subaddresses = m_subaddress->getAll(); @@ -758,33 +799,39 @@ extern "C" return subaddresses; } + FUNCTION_VISABILITY_ATTRIBUTE int32_t subaddrress_size() { std::vector _subaddresses = m_subaddress->getAll(); return _subaddresses.size(); } + FUNCTION_VISABILITY_ATTRIBUTE void subaddress_add_row(uint32_t accountIndex, char *label) { m_subaddress->addRow(accountIndex, std::string(label)); } + FUNCTION_VISABILITY_ATTRIBUTE void subaddress_set_label(uint32_t accountIndex, uint32_t addressIndex, char *label) { m_subaddress->setLabel(accountIndex, addressIndex, std::string(label)); } + FUNCTION_VISABILITY_ATTRIBUTE void subaddress_refresh(uint32_t accountIndex) { m_subaddress->refresh(accountIndex); } + FUNCTION_VISABILITY_ATTRIBUTE int32_t account_size() { std::vector _accocunts = m_account->getAll(); return _accocunts.size(); } + FUNCTION_VISABILITY_ATTRIBUTE int64_t *account_get_all() { std::vector _accocunts = m_account->getAll(); @@ -801,21 +848,25 @@ extern "C" return accocunts; } + FUNCTION_VISABILITY_ATTRIBUTE void account_add_row(char *label) { m_account->addRow(std::string(label)); } + FUNCTION_VISABILITY_ATTRIBUTE void account_set_label_row(uint32_t account_index, char *label) { m_account->setLabel(account_index, label); } + FUNCTION_VISABILITY_ATTRIBUTE void account_refresh() { m_account->refresh(); } + FUNCTION_VISABILITY_ATTRIBUTE int64_t *transactions_get_all() { std::vector transactions = m_transaction_history->getAll(); @@ -832,16 +883,19 @@ extern "C" return transactionAddresses; } + FUNCTION_VISABILITY_ATTRIBUTE void transactions_refresh() { m_transaction_history->refresh(); } + FUNCTION_VISABILITY_ATTRIBUTE int64_t transactions_count() { return m_transaction_history->count(); } + FUNCTION_VISABILITY_ATTRIBUTE int LedgerExchange( unsigned char *command, unsigned int cmd_len, @@ -851,37 +905,44 @@ extern "C" return -1; } + FUNCTION_VISABILITY_ATTRIBUTE int LedgerFind(char *buffer, size_t len) { return -1; } + FUNCTION_VISABILITY_ATTRIBUTE void on_startup() { Monero::Utils::onStartup(); Monero::WalletManagerFactory::setLogLevel(0); } + FUNCTION_VISABILITY_ATTRIBUTE void rescan_blockchain() { m_wallet->rescanBlockchainAsync(); } + FUNCTION_VISABILITY_ATTRIBUTE char * get_tx_key(char * txId) { return strdup(m_wallet->getTxKey(std::string(txId)).c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE char *get_subaddress_label(uint32_t accountIndex, uint32_t addressIndex) { return strdup(get_current_wallet()->getSubaddressLabel(accountIndex, addressIndex).c_str()); } + FUNCTION_VISABILITY_ATTRIBUTE void set_trusted_daemon(bool arg) { m_wallet->setTrustedDaemon(arg); } + FUNCTION_VISABILITY_ATTRIBUTE bool trusted_daemon() { return m_wallet->trustedDaemon(); diff --git a/cw_monero/lib/api/monero_api.dart b/cw_monero/lib/api/monero_api.dart index 398d737d1..3b502ac16 100644 --- a/cw_monero/lib/api/monero_api.dart +++ b/cw_monero/lib/api/monero_api.dart @@ -3,4 +3,4 @@ import 'dart:io'; final DynamicLibrary moneroApi = Platform.isAndroid ? DynamicLibrary.open("libcw_monero.so") - : DynamicLibrary.open("cw_monero.framework/cw_monero"); \ No newline at end of file + : DynamicLibrary.process(); diff --git a/cw_monero/lib/monero_subaddress_list.dart b/cw_monero/lib/monero_subaddress_list.dart index 53efc1251..0dcddc679 100644 --- a/cw_monero/lib/monero_subaddress_list.dart +++ b/cw_monero/lib/monero_subaddress_list.dart @@ -22,7 +22,7 @@ abstract class MoneroSubaddressListBase with Store { bool _isUpdating; void update({required int accountIndex}) { - refreshCoins(accountIndex); + // refreshCoins(accountIndex); if (_isUpdating) { return; diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 76563310e..12381af44 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -39,8 +39,10 @@ class MoneroWallet = MoneroWalletBase with _$MoneroWallet; abstract class MoneroWalletBase extends WalletBase with Store { - MoneroWalletBase({required WalletInfo walletInfo, - required Box unspentCoinsInfo}) + MoneroWalletBase({ + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required String password}) : balance = ObservableMap.of({ CryptoCurrency.xmr: MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: 0), @@ -48,6 +50,7 @@ abstract class MoneroWalletBase extends WalletBase monero_wallet.getSeed(); + @override + String get password => _password; + @override MoneroWalletKeys get keys => MoneroWalletKeys( privateSpendKey: monero_wallet.getSecretSpendKey(), @@ -99,6 +105,7 @@ abstract class MoneroWalletBase extends WalletBase unspentCoins; + String _password; Future init() async { await walletAddresses.init(); @@ -352,6 +359,7 @@ abstract class MoneroWalletBase extends WalletBase changePassword(String password) async { monero_wallet.setPasswordSync(password); + _password = password; } Future getNodeHeight() async => monero_wallet.getNodeHeight(); @@ -378,7 +386,7 @@ abstract class MoneroWalletBase extends WalletBase updateUnspent() async { - refreshCoins(walletAddresses.account!.id); + // refreshCoins(walletAddresses.account!.id); unspentCoins.clear(); diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 90c63fb72..181bc7c66 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -73,7 +73,9 @@ class MoneroWalletService extends WalletService< password: credentials.password!, language: credentials.language); final wallet = MoneroWallet( - walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); + + walletInfo: credentials.walletInfo!, + password: credentials.password!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -109,7 +111,9 @@ class MoneroWalletService extends WalletService< .openWalletAsync({'path': path, 'password': password}); final walletInfo = walletInfoSource.values.firstWhere( (info) => info.id == WalletBase.idFor(name, getType())); - final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + final wallet = MoneroWallet( + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, + password: password); final isValid = wallet.walletAddresses.validate(); if (!isValid) { @@ -160,7 +164,7 @@ class MoneroWalletService extends WalletService< final currentWalletInfo = walletInfoSource.values.firstWhere( (info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = - MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource, password: password); await currentWallet.renameWalletFiles(newName); @@ -185,7 +189,9 @@ class MoneroWalletService extends WalletService< viewKey: credentials.viewKey, spendKey: credentials.spendKey); final wallet = MoneroWallet( - walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); + + walletInfo: credentials.walletInfo!, + password: credentials.password!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -207,7 +213,9 @@ class MoneroWalletService extends WalletService< seed: credentials.mnemonic, restoreHeight: credentials.height!); final wallet = MoneroWallet( - walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); + + walletInfo: credentials.walletInfo!, + password: credentials.password!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; diff --git a/cw_monero/linux/CMakeLists.txt b/cw_monero/linux/CMakeLists.txt new file mode 100644 index 000000000..ba685269d --- /dev/null +++ b/cw_monero/linux/CMakeLists.txt @@ -0,0 +1,270 @@ +# The Flutter tooling requires that developers have CMake 3.10 or later +# installed. You should not increase this version, as doing so will cause +# the plugin to fail to compile for some customers of the plugin. +cmake_minimum_required(VERSION 3.10) + +# Project-level configuration. +set(PROJECT_NAME "cw_monero") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed. +set(PLUGIN_NAME "cw_monero_plugin") + +# Define the plugin library target. Its name must not be changed (see comment +# on PLUGIN_NAME above). +# +# Any new source files that you add to the plugin should be added here. +add_library(${PLUGIN_NAME} SHARED + "cw_monero_plugin.cc" + "../ios/Classes/monero_api.cpp" +) + +# Apply a standard set of build settings that are configured in the +# application-level CMakeLists.txt. This can be removed for plugins that want +# full control over build settings. +apply_standard_settings(${PLUGIN_NAME}) + +# Symbols are hidden by default to reduce the chance of accidental conflicts +# between plugins. This should not be removed; any symbols that should be +# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) + +# Source include directories and library dependencies. Add any plugin-specific +# dependencies here. +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) +target_link_libraries(${PLUGIN_NAME} PUBLIC cw_monero) +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(cw_monero_bundled_libraries + "" + PARENT_SCOPE +) + +add_library( cw_monero + STATIC + ../ios/Classes/monero_api.cpp) + +set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../cw_shared_external/ios/External/linux) + +############ +# libsodium +############ + +add_library(sodium STATIC IMPORTED) +set_target_properties(sodium PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libsodium.a) + +############ +# OpenSSL +############ + +add_library(crypto STATIC IMPORTED) +set_target_properties(crypto PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libcrypto.a) + +add_library(ssl STATIC IMPORTED) +set_target_properties(ssl PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libssl.a) + +############ +# Boost +############ + +add_library(boost_chrono STATIC IMPORTED) +set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_chrono.a) + +add_library(boost_date_time STATIC IMPORTED) +set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_date_time.a) + +add_library(boost_filesystem STATIC IMPORTED) +set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_filesystem.a) + +add_library(boost_program_options STATIC IMPORTED) +set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_program_options.a) + +add_library(boost_regex STATIC IMPORTED) +set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_regex.a) + +add_library(boost_serialization STATIC IMPORTED) +set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_serialization.a) + +add_library(boost_system STATIC IMPORTED) +set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_system.a) + +add_library(boost_thread STATIC IMPORTED) +set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_thread.a) + +add_library(boost_wserialization STATIC IMPORTED) +set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libboost_wserialization.a) + +############# +# Monero +############# + + +add_library(wallet STATIC IMPORTED) +set_target_properties(wallet PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libwallet.a) + +add_library(wallet_api STATIC IMPORTED) +set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libwallet_api.a) + +add_library(cryptonote_core STATIC IMPORTED) +set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libcryptonote_core.a) + +add_library(cryptonote_basic STATIC IMPORTED) +set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libcryptonote_basic.a) + +add_library(cryptonote_format_utils_basic STATIC IMPORTED) +set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libcryptonote_format_utils_basic.a) + +add_library(mnemonics STATIC IMPORTED) +set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libmnemonics.a) + +add_library(common STATIC IMPORTED) +set_target_properties(common PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libcommon.a) + +add_library(cncrypto STATIC IMPORTED) +set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libcncrypto.a) + +add_library(ringct STATIC IMPORTED) +set_target_properties(ringct PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libringct.a) + +add_library(ringct_basic STATIC IMPORTED) +set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libringct_basic.a) + +add_library(blockchain_db STATIC IMPORTED) +set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libblockchain_db.a) + +add_library(lmdb STATIC IMPORTED) +set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/liblmdb.a) + +add_library(easylogging STATIC IMPORTED) +set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libeasylogging.a) + +add_library(epee STATIC IMPORTED) +set_target_properties(epee PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libepee.a) + +add_library(blocks STATIC IMPORTED) +set_target_properties(blocks PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libblocks.a) + +add_library(checkpoints STATIC IMPORTED) +set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libcheckpoints.a) + +add_library(device STATIC IMPORTED) +set_target_properties(device PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libdevice.a) + +add_library(device_trezor STATIC IMPORTED) +set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libdevice_trezor.a) + +add_library(multisig STATIC IMPORTED) +set_target_properties(multisig PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libmultisig.a) + +add_library(version STATIC IMPORTED) +set_target_properties(version PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libversion.a) + +add_library(net STATIC IMPORTED) +set_target_properties(net PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libnet.a) + +add_library(hardforks STATIC IMPORTED) +set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libhardforks.a) + +add_library(randomx STATIC IMPORTED) +set_target_properties(randomx PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/librandomx.a) + +add_library(rpc_base STATIC IMPORTED) +set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/librpc_base.a) + +add_library(wallet-crypto STATIC IMPORTED) +set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/monero/libwallet-crypto.a) + +add_library(unbound STATIC IMPORTED) +set_target_properties(unbound PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/lib/libunbound.a) + +include_directories( ${EXTERNAL_LIBS_DIR}/include ) + +target_link_libraries( cw_monero + + wallet_api + wallet + cryptonote_core + cryptonote_basic + cryptonote_format_utils_basic + mnemonics + ringct + ringct_basic + net + common + cncrypto + blockchain_db + lmdb + easylogging + unbound + epee + blocks + checkpoints + device + device_trezor + multisig + version + randomx + hardforks + rpc_base + wallet-crypto + + boost_chrono + boost_date_time + boost_filesystem + boost_program_options + boost_regex + boost_serialization + boost_system + boost_thread + boost_wserialization + + ssl + crypto + + sodium + ) diff --git a/cw_monero/linux/cw_monero_plugin.cc b/cw_monero/linux/cw_monero_plugin.cc new file mode 100644 index 000000000..ca8524c9e --- /dev/null +++ b/cw_monero/linux/cw_monero_plugin.cc @@ -0,0 +1,70 @@ +#include "include/cw_monero/cw_monero_plugin.h" + +#include +#include +#include + +#include + +#define CW_MONERO_PLUGIN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), cw_monero_plugin_get_type(), \ + CwMoneroPlugin)) + +struct _CwMoneroPlugin { + GObject parent_instance; +}; + +G_DEFINE_TYPE(CwMoneroPlugin, cw_monero_plugin, g_object_get_type()) + +// Called when a method call is received from Flutter. +static void cw_monero_plugin_handle_method_call( + CwMoneroPlugin* self, + FlMethodCall* method_call) { + g_autoptr(FlMethodResponse) response = nullptr; + + const gchar* method = fl_method_call_get_name(method_call); + + if (strcmp(method, "getPlatformVersion") == 0) { + struct utsname uname_data = {}; + uname(&uname_data); + g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version); + g_autoptr(FlValue) result = fl_value_new_string(version); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else { + response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); + } + + fl_method_call_respond(method_call, response, nullptr); +} + +static void cw_monero_plugin_dispose(GObject* object) { + G_OBJECT_CLASS(cw_monero_plugin_parent_class)->dispose(object); +} + +static void cw_monero_plugin_class_init(CwMoneroPluginClass* klass) { + G_OBJECT_CLASS(klass)->dispose = cw_monero_plugin_dispose; +} + +static void cw_monero_plugin_init(CwMoneroPlugin* self) {} + +static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + CwMoneroPlugin* plugin = CW_MONERO_PLUGIN(user_data); + cw_monero_plugin_handle_method_call(plugin, method_call); +} + +void cw_monero_plugin_register_with_registrar(FlPluginRegistrar* registrar) { + CwMoneroPlugin* plugin = CW_MONERO_PLUGIN( + g_object_new(cw_monero_plugin_get_type(), nullptr)); + + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); + g_autoptr(FlMethodChannel) channel = + fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), + "cw_monero", + FL_METHOD_CODEC(codec)); + fl_method_channel_set_method_call_handler(channel, method_call_cb, + g_object_ref(plugin), + g_object_unref); + + g_object_unref(plugin); +} diff --git a/cw_monero/linux/include/cw_monero/cw_monero_plugin.h b/cw_monero/linux/include/cw_monero/cw_monero_plugin.h new file mode 100644 index 000000000..387903ff6 --- /dev/null +++ b/cw_monero/linux/include/cw_monero/cw_monero_plugin.h @@ -0,0 +1,26 @@ +#ifndef FLUTTER_PLUGIN_CW_MONERO_PLUGIN_H_ +#define FLUTTER_PLUGIN_CW_MONERO_PLUGIN_H_ + +#include + +G_BEGIN_DECLS + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + +typedef struct _CwMoneroPlugin CwMoneroPlugin; +typedef struct { + GObjectClass parent_class; +} CwMoneroPluginClass; + +FLUTTER_PLUGIN_EXPORT GType cw_monero_plugin_get_type(); + +FLUTTER_PLUGIN_EXPORT void cw_monero_plugin_register_with_registrar( + FlPluginRegistrar* registrar); + +G_END_DECLS + +#endif // FLUTTER_PLUGIN_CW_MONERO_PLUGIN_H_ diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index 56548e79e..e1cbb5b59 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -20,8 +20,6 @@ using namespace std::chrono_literals; extern "C" { #endif - const uint64_t MONERO_BLOCK_SIZE = 1000; - struct Utf8Box { char *value; @@ -149,7 +147,8 @@ extern "C" fee = transaction->fee(); blockHeight = transaction->blockHeight(); subaddrAccount = transaction->subaddrAccount(); - std::set::iterator it = transaction->subaddrIndex().begin(); + std::set subIndex = transaction->subaddrIndex(); + std::set::iterator it = subIndex.begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); datetime = static_cast(transaction->timestamp()); diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index cf2993ef3..cdc6245b0 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -46,9 +46,10 @@ flutter: pluginClass: CwMoneroPlugin ios: pluginClass: CwMoneroPlugin - macos: pluginClass: CwMoneroPlugin + linux: + pluginClass: CwMoneroPlugin # To add assets to your plugin package, add an assets section, like this: # assets: diff --git a/ios/Podfile b/ios/Podfile index 027d48ceb..b29d40484 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -44,7 +44,6 @@ post_install do |installer| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4bc10f9be..424adbfec 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -10,8 +10,8 @@ 0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C44A7192518EF8000B570ED /* decrypt.swift */; }; 0C9D68C9264854B60011B691 /* secRandom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9D68C8264854B60011B691 /* secRandom.swift */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 20ED0868E1BD7E12278C0CB3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 4DFD1BB54A3A50573E19A583 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C663361C56EBB242598F609 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -23,13 +23,13 @@ 0C44A7192518EF8000B570ED /* decrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = decrypt.swift; sourceTree = ""; }; 0C9986A3251A932F00D566FD /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0C9D68C8264854B60011B691 /* secRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = secRandom.swift; sourceTree = ""; }; - 11F9FC13F9EE2A705B213FA9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 1F083F2041D1F553F2AF8B62 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 20F67A1B2C2FCB2A3BB048C1 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3C663361C56EBB242598F609 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 501EA9286675DC8636978EA4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 5AFFEBFC279AD49C00F906A4 /* wakeLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = wakeLock.swift; sourceTree = ""; }; + 61CAA8652B54F23356F7592A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -40,7 +40,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - AD0937B0140D5A4C24E73BEA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -48,7 +48,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4DFD1BB54A3A50573E19A583 /* Pods_Runner.framework in Frameworks */, + 20ED0868E1BD7E12278C0CB3 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -59,7 +59,7 @@ isa = PBXGroup; children = ( 0C9986A3251A932F00D566FD /* CryptoSwift.framework */, - 3C663361C56EBB242598F609 /* Pods_Runner.framework */, + B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -77,9 +77,9 @@ 84389F1A05D5860790D82820 /* Pods */ = { isa = PBXGroup; children = ( - 11F9FC13F9EE2A705B213FA9 /* Pods-Runner.debug.xcconfig */, - 1F083F2041D1F553F2AF8B62 /* Pods-Runner.release.xcconfig */, - AD0937B0140D5A4C24E73BEA /* Pods-Runner.profile.xcconfig */, + 20F67A1B2C2FCB2A3BB048C1 /* Pods-Runner.debug.xcconfig */, + 501EA9286675DC8636978EA4 /* Pods-Runner.release.xcconfig */, + 61CAA8652B54F23356F7592A /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -138,13 +138,13 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - B91154210ADCED81FBF06A85 /* [CP] Check Pods Manifest.lock */, + 0843B0813AFBAF53935AD24E /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 32D0076A9969C0C38D68AF62 /* [CP] Embed Pods Frameworks */, + DD8DB3179CA4E511F9954A6F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -203,21 +203,26 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 32D0076A9969C0C38D68AF62 /* [CP] Embed Pods Frameworks */ = { + 0843B0813AFBAF53935AD24E /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { @@ -250,26 +255,21 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; - B91154210ADCED81FBF06A85 /* [CP] Check Pods Manifest.lock */ = { + DD8DB3179CA4E511F9954A6F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -390,7 +390,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VALID_ARCHS = arm64; VERSIONING_SYSTEM = "apple-generic"; }; @@ -537,7 +537,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VALID_ARCHS = arm64; VERSIONING_SYSTEM = "apple-generic"; }; @@ -574,7 +574,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VALID_ARCHS = arm64; VERSIONING_SYSTEM = "apple-generic"; }; diff --git a/lib/anonpay/anonpay_invoice_info.dart b/lib/anonpay/anonpay_invoice_info.dart index bd6776d00..89613224e 100644 --- a/lib/anonpay/anonpay_invoice_info.dart +++ b/lib/anonpay/anonpay_invoice_info.dart @@ -1,5 +1,4 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; -import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/keyable.dart'; import 'package:hive/hive.dart'; @@ -36,7 +35,7 @@ class AnonpayInvoiceInfo extends HiveObject with Keyable implements AnonpayInfoB @HiveField(13) final String provider; - static const typeId = ANONPAY_INVOICE_INFO_TYPE_ID; + static const typeId = 10; static const boxName = 'AnonpayInvoiceInfo'; AnonpayInvoiceInfo({ diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 3164aacaa..f03e47460 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -22,8 +22,9 @@ class CWBitcoin extends Bitcoin { @override WalletCredentials createBitcoinNewWalletCredentials({ required String name, - WalletInfo? walletInfo}) - => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); + WalletInfo? walletInfo, + String? password}) + => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo, password: password); @override List getWordList() => wordlist; @@ -138,12 +139,12 @@ class CWBitcoin extends Bitcoin { await bitcoinWallet.updateUnspent(); } - WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return BitcoinWalletService(walletInfoSource, unspentCoinSource); + WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource, bool isDirect) { + return BitcoinWalletService(walletInfoSource, unspentCoinSource, isDirect); } - WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return LitecoinWalletService(walletInfoSource, unspentCoinSource); + WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource, bool isDirect) { + return LitecoinWalletService(walletInfoSource, unspentCoinSource, isDirect); } @override diff --git a/lib/buy/moonpay/moonpay_buy_provider.dart b/lib/buy/moonpay/moonpay_buy_provider.dart index 0736edeb7..ab62fcf68 100644 --- a/lib/buy/moonpay/moonpay_buy_provider.dart +++ b/lib/buy/moonpay/moonpay_buy_provider.dart @@ -16,11 +16,11 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cw_core/crypto_currency.dart'; class MoonPaySellProvider { - MoonPaySellProvider({this.isTest = false}) - : baseUrl = isTest ? _baseTestUrl : _baseProductUrl; + MoonPaySellProvider({this.isTest = false}) : baseUrl = isTest ? _baseTestUrl : _baseProductUrl; static const _baseTestUrl = 'sell-sandbox.moonpay.com'; static const _baseProductUrl = 'sell.moonpay.com'; + static String themeToMoonPayTheme(ThemeBase theme) { switch (theme.type) { case ThemeType.bright: @@ -31,16 +31,17 @@ class MoonPaySellProvider { return 'dark'; } } - static String get _apiKey => secrets.moonPayApiKey; - static String get _secretKey => secrets.moonPaySecretKey; + + static String get _apiKey => secrets.moonPayApiKey; + + static String get _secretKey => secrets.moonPaySecretKey; final bool isTest; final String baseUrl; Future requestUrl( {required CryptoCurrency currency, - required String refundWalletAddress, - required SettingsStore settingsStore}) async { - + required String refundWalletAddress, + required SettingsStore settingsStore}) async { final customParams = { 'theme': themeToMoonPayTheme(settingsStore.currentTheme), 'language': settingsStore.languageCode, @@ -50,11 +51,13 @@ class MoonPaySellProvider { }; final originalUri = Uri.https( - baseUrl, '', { - 'apiKey': _apiKey, - 'defaultBaseCurrencyCode': currency.toString().toLowerCase(), - 'refundWalletAddress': refundWalletAddress - }..addAll(customParams)); + baseUrl, + '', + { + 'apiKey': _apiKey, + 'defaultBaseCurrencyCode': currency.toString().toLowerCase(), + 'refundWalletAddress': refundWalletAddress + }..addAll(customParams)); final messageBytes = utf8.encode('?${originalUri.query}'); final key = utf8.encode(_secretKey); final hmac = Hmac(sha256, key); @@ -93,8 +96,7 @@ class MoonPayBuyProvider extends BuyProvider { @override BuyProviderDescription get description => BuyProviderDescription.moonPay; - String get currencyCode => - walletTypeToCryptoCurrency(walletType).title.toLowerCase(); + String get currencyCode => walletTypeToCryptoCurrency(walletType).title.toLowerCase(); @override String get trackUrl => baseUrl + '/transaction_receipt?transactionId='; @@ -103,16 +105,24 @@ class MoonPayBuyProvider extends BuyProvider { @override Future requestUrl(String amount, String sourceCurrency) async { - final enabledPaymentMethods = - 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' + final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' '%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment'; - final suffix = '?apiKey=' + _apiKey + '¤cyCode=' + - currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods + - '&walletAddress=' + walletAddress + - '&baseCurrencyCode=' + sourceCurrency.toLowerCase() + - '&baseCurrencyAmount=' + amount + '&lockAmount=true' + - '&showAllCurrencies=false' + '&showWalletAddressForm=false'; + final suffix = '?apiKey=' + + _apiKey + + '¤cyCode=' + + currencyCode + + '&enabledPaymentMethods=' + + enabledPaymentMethods + + '&walletAddress=' + + walletAddress + + '&baseCurrencyCode=' + + sourceCurrency.toLowerCase() + + '&baseCurrencyAmount=' + + amount + + '&lockAmount=true' + + '&showAllCurrencies=false' + + '&showWalletAddressForm=false'; final originalUrl = baseUrl + suffix; @@ -121,25 +131,28 @@ class MoonPayBuyProvider extends BuyProvider { final hmac = Hmac(sha256, key); final digest = hmac.convert(messageBytes); final signature = base64.encode(digest.bytes); - final urlWithSignature = originalUrl + - '&signature=${Uri.encodeComponent(signature)}'; + final urlWithSignature = originalUrl + '&signature=${Uri.encodeComponent(signature)}'; return isTestEnvironment ? originalUrl : urlWithSignature; } @override Future calculateAmount(String amount, String sourceCurrency) async { - final url = _apiUrl + _currenciesSuffix + '/$currencyCode' + - _quoteSuffix + '/?apiKey=' + _apiKey + - '&baseCurrencyAmount=' + amount + - '&baseCurrencyCode=' + sourceCurrency.toLowerCase(); + final url = _apiUrl + + _currenciesSuffix + + '/$currencyCode' + + _quoteSuffix + + '/?apiKey=' + + _apiKey + + '&baseCurrencyAmount=' + + amount + + '&baseCurrencyCode=' + + sourceCurrency.toLowerCase(); final uri = Uri.parse(url); final response = await get(uri); if (response.statusCode != 200) { - throw BuyException( - description: description, - text: 'Quote is not found!'); + throw BuyException(description: description, text: 'Quote is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -148,22 +161,17 @@ class MoonPayBuyProvider extends BuyProvider { final minSourceAmount = responseJSON['baseCurrency']['minAmount'] as int; return BuyAmount( - sourceAmount: sourceAmount, - destAmount: destAmount, - minAmount: minSourceAmount); + sourceAmount: sourceAmount, destAmount: destAmount, minAmount: minSourceAmount); } @override Future findOrderById(String id) async { - final url = _apiUrl + _transactionsSuffix + '/$id' + - '?apiKey=' + _apiKey; + final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey; final uri = Uri.parse(url); final response = await get(uri); if (response.statusCode != 200) { - throw BuyException( - description: description, - text: 'Transaction $id is not found!'); + throw BuyException(description: description, text: 'Transaction $id is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -181,8 +189,7 @@ class MoonPayBuyProvider extends BuyProvider { createdAt: createdAt, amount: amount.toString(), receiveAddress: walletAddress, - walletId: walletId - ); + walletId: walletId); } static Future onEnabled() async { @@ -201,4 +208,4 @@ class MoonPayBuyProvider extends BuyProvider { return isBuyEnable; } -} \ No newline at end of file +} diff --git a/lib/buy/order.dart b/lib/buy/order.dart index 5a677d291..387fbcd34 100644 --- a/lib/buy/order.dart +++ b/lib/buy/order.dart @@ -1,8 +1,7 @@ import 'package:cake_wallet/buy/buy_provider_description.dart'; +import 'package:hive/hive.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:hive/hive.dart'; part 'order.g.dart'; @@ -27,7 +26,7 @@ class Order extends HiveObject { } } - static const typeId = ORDER_TYPE_ID; + static const typeId = 8; static const boxName = 'Orders'; static const boxKey = 'ordersBoxKey'; @@ -67,4 +66,4 @@ class Order extends HiveObject { BuyProviderDescription.deserialize(raw: providerRaw); String amountFormatted() => formatAmount(amount); -} +} \ No newline at end of file diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 854640015..5a48f76e4 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -3,7 +3,7 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; @@ -31,7 +31,7 @@ class AuthService with Store { Routes.restoreOptions, ]; - final FlutterSecureStorage secureStorage; + final SecureStorage secureStorage; final SharedPreferences sharedPreferences; final SettingsStore settingsStore; @@ -106,7 +106,7 @@ class AuthService with Store { } } - + Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { if (!isAuthenticatedSuccessfully) { @@ -140,8 +140,8 @@ class AuthService with Store { } } } - + }); - + } } diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 6476891ed..03581f156 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,15 +1,16 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cw_core/root_dir.dart'; +import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:path_provider/path_provider.dart'; import 'package:cryptography/cryptography.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:archive/archive_io.dart'; -import 'package:cw_core/cake_hive.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; @@ -17,7 +18,6 @@ import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/wallet_types.g.dart'; - import 'package:cake_backup/backup.dart' as cake_backup; class BackupService { @@ -32,7 +32,7 @@ class BackupService { static const _v2 = 2; final Cipher _cipher; - final FlutterSecureStorage _flutterSecureStorage; + final SecureStorage _flutterSecureStorage; final SharedPreferences _sharedPreferences; final Box _walletInfoSource; final KeyService _keyService; @@ -74,7 +74,7 @@ class BackupService { Future _exportBackupV2(String password) async { final zipEncoder = ZipFileEncoder(); - final appDir = await getApplicationDocumentsDirectory(); + final appDir = await getAppDir(); final now = DateTime.now(); final tmpDir = Directory('${appDir.path}/~_BACKUP_TMP'); final archivePath = '${tmpDir.path}/backup_${now.toString()}.zip'; @@ -114,7 +114,7 @@ class BackupService { } Future _importBackupV1(Uint8List data, String password, {required String nonce}) async { - final appDir = await getApplicationDocumentsDirectory(); + final appDir = await getAppDir(); final decryptedData = await _decryptV1(data, password, nonce); final zip = ZipDecoder().decodeBytes(decryptedData); @@ -137,7 +137,7 @@ class BackupService { } Future _importBackupV2(Uint8List data, String password) async { - final appDir = await getApplicationDocumentsDirectory(); + final appDir = await getAppDir(); final decryptedData = await _decryptV2(data, password); final zip = ZipDecoder().decodeBytes(decryptedData); @@ -170,19 +170,19 @@ class BackupService { } Future> _reloadHiveWalletInfoBox() async { - final appDir = await getApplicationDocumentsDirectory(); - await CakeHive.close(); - CakeHive.init(appDir.path); + final appDir = await getAppDir(); + await Hive.close(); + Hive.init(appDir.path); - if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { - CakeHive.registerAdapter(WalletInfoAdapter()); + if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { + Hive.registerAdapter(WalletInfoAdapter()); } - return await CakeHive.openBox(WalletInfo.boxName); + return await Hive.openBox(WalletInfo.boxName); } Future _importPreferencesDump() async { - final appDir = await getApplicationDocumentsDirectory(); + final appDir = await getAppDir(); final preferencesFile = File('${appDir.path}/~_preferences_dump'); if (!preferencesFile.existsSync()) { @@ -375,7 +375,7 @@ class BackupService { Future _importKeychainDumpV1(String password, {required String nonce, String keychainSalt = secrets.backupKeychainSalt}) async { - final appDir = await getApplicationDocumentsDirectory(); + final appDir = await getAppDir(); final keychainDumpFile = File('${appDir.path}/~_keychain_dump'); final decryptedKeychainDumpFileData = await _decryptV1(keychainDumpFile.readAsBytesSync(), '$keychainSalt$password', nonce); @@ -401,7 +401,7 @@ class BackupService { Future _importKeychainDumpV2(String password, {String keychainSalt = secrets.backupKeychainSalt}) async { - final appDir = await getApplicationDocumentsDirectory(); + final appDir = await getAppDir(); final keychainDumpFile = File('${appDir.path}/~_keychain_dump'); final decryptedKeychainDumpFileData = await _decryptV2(keychainDumpFile.readAsBytesSync(), '$keychainSalt$password'); diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index 337f1ef21..a15c92784 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -1,11 +1,11 @@ -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/encrypt.dart'; class KeyService { KeyService(this._secureStorage); - final FlutterSecureStorage _secureStorage; + final SecureStorage _secureStorage; Future getWalletPassword({required String walletName}) async { final key = generateStoreKeyFor( diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 3b28f36c3..25f2d75be 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -2,7 +2,6 @@ import 'package:cake_wallet/di.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/core/key_service.dart'; @@ -15,7 +14,6 @@ import 'package:cw_core/wallet_type.dart'; class WalletCreationService { WalletCreationService( {required WalletType initialType, - required this.secureStorage, required this.keyService, required this.sharedPreferences, required this.walletInfoSource}) @@ -24,7 +22,6 @@ class WalletCreationService { } WalletType type; - final FlutterSecureStorage secureStorage; final SharedPreferences sharedPreferences; final KeyService keyService; final Box walletInfoSource; @@ -58,10 +55,13 @@ class WalletCreationService { Future create(WalletCredentials credentials) async { checkIfExists(credentials.name); - final password = generateWalletPassword(); - credentials.password = password; - await keyService.saveWalletPassword( - password: password, walletName: credentials.name); + + if (credentials.password == null) { + credentials.password = generateWalletPassword(); + await keyService.saveWalletPassword( + password: credentials.password!, walletName: credentials.name); + } + final wallet = await _service!.create(credentials); if (wallet.type == WalletType.monero) { @@ -76,10 +76,13 @@ class WalletCreationService { Future restoreFromKeys(WalletCredentials credentials) async { checkIfExists(credentials.name); - final password = generateWalletPassword(); - credentials.password = password; - await keyService.saveWalletPassword( - password: password, walletName: credentials.name); + + if (credentials.password == null) { + credentials.password = generateWalletPassword(); + await keyService.saveWalletPassword( + password: credentials.password!, walletName: credentials.name); + } + final wallet = await _service!.restoreFromKeys(credentials); if (wallet.type == WalletType.monero) { @@ -94,10 +97,13 @@ class WalletCreationService { Future restoreFromSeed(WalletCredentials credentials) async { checkIfExists(credentials.name); - final password = generateWalletPassword(); - credentials.password = password; - await keyService.saveWalletPassword( - password: password, walletName: credentials.name); + + if (credentials.password == null) { + credentials.password = generateWalletPassword(); + await keyService.saveWalletPassword( + password: credentials.password!, walletName: credentials.name); + } + final wallet = await _service!.restoreFromSeed(credentials); if (wallet.type == WalletType.monero) { diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart index 3323e7831..9596015bc 100644 --- a/lib/core/wallet_loading_service.dart +++ b/lib/core/wallet_loading_service.dart @@ -7,26 +7,24 @@ import 'package:cw_core/wallet_type.dart'; import 'package:shared_preferences/shared_preferences.dart'; class WalletLoadingService { - WalletLoadingService( - this.sharedPreferences, this.keyService, this.walletServiceFactory); + WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory); final SharedPreferences sharedPreferences; final KeyService keyService; final WalletService Function(WalletType type) walletServiceFactory; - Future renameWallet( - WalletType type, String name, String newName) async { + Future renameWallet(WalletType type, String name, String newName, + {String? password}) async { final walletService = walletServiceFactory.call(type); - final password = await keyService.getWalletPassword(walletName: name); + final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); // Save the current wallet's password to the new wallet name's key - await keyService.saveWalletPassword( - walletName: newName, password: password); + await keyService.saveWalletPassword(walletName: newName, password: walletPassword); // Delete previous wallet name from keyService to keep only new wallet's name // otherwise keeps duplicate (old and new names) await keyService.deleteWalletPassword(walletName: name); - await walletService.rename(name, password, newName); + await walletService.rename(name, walletPassword, newName); // set shared preferences flag based on previous wallet name if (type == WalletType.monero) { @@ -37,10 +35,10 @@ class WalletLoadingService { } } - Future load(WalletType type, String name) async { + Future load(WalletType type, String name, {String? password}) async { final walletService = walletServiceFactory.call(type); - final password = await keyService.getWalletPassword(walletName: name); - final wallet = await walletService.openWallet(name, password); + final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); + final wallet = await walletService.openWallet(name, walletPassword); if (type == WalletType.monero) { await updateMoneroWalletPassword(wallet); @@ -61,11 +59,9 @@ class WalletLoadingService { // Save new generated password with backup key for case where // wallet will change password, but it will fail to update in secure storage final bakWalletName = '#__${wallet.name}_bak__#'; - await keyService.saveWalletPassword( - walletName: bakWalletName, password: password); + await keyService.saveWalletPassword(walletName: bakWalletName, password: password); await wallet.changePassword(password); - await keyService.saveWalletPassword( - walletName: wallet.name, password: password); + await keyService.saveWalletPassword(walletName: wallet.name, password: password); isPasswordUpdated = true; await sharedPreferences.setBool(key, isPasswordUpdated); } diff --git a/lib/di.dart b/lib/di.dart index 80a55e1c6..eb4660424 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/anonpay/anonpay_api.dart'; import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; @@ -32,6 +33,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; +import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -79,6 +81,8 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cw_core/erc20_token.dart'; +import 'package:cake_wallet/view_model/wallet_unlock_loadable_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_unlock_verifiable_view_model.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cw_core/wallet_service.dart'; @@ -176,7 +180,7 @@ import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/wallet_type.dart'; @@ -201,6 +205,7 @@ import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_page.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; import 'core/totp_request_details.dart'; @@ -269,7 +274,7 @@ Future setup({ getIt.registerFactory>(() => _nodeSource); - getIt.registerSingleton(FlutterSecureStorage()); + getIt.registerSingleton(secureStorageShared); getIt.registerSingleton(AuthenticationStore()); getIt.registerSingleton(WalletListStore()); getIt.registerSingleton(NodeListStoreBase.instance); @@ -290,22 +295,21 @@ Future setup({ getIt.registerSingleton( ExchangeTemplateStore(templateSource: _exchangeTemplates)); getIt.registerSingleton( - YatStore(appStore: getIt.get(), secureStorage: getIt.get()) + YatStore(appStore: getIt.get(), secureStorage: getIt.get()) ..init()); getIt.registerSingleton( AnonpayTransactionsStore(anonpayInvoiceInfoSource: _anonpayInvoiceInfoSource)); - final secretStore = await SecretStoreBase.load(getIt.get()); + final secretStore = await SecretStoreBase.load(getIt.get()); getIt.registerSingleton(secretStore); - getIt.registerFactory(() => KeyService(getIt.get())); + getIt.registerFactory(() => KeyService(getIt.get())); getIt.registerFactoryParam((type, _) => WalletCreationService( initialType: type, keyService: getIt.get(), - secureStorage: getIt.get(), sharedPreferences: getIt.get(), walletInfoSource: _walletInfoSource)); @@ -346,7 +350,7 @@ Future setup({ getIt.registerFactory( () => AuthService( - secureStorage: getIt.get(), + secureStorage: getIt.get(), sharedPreferences: getIt.get(), settingsStore: getIt.get(), ), @@ -733,11 +737,17 @@ Future setup({ case WalletType.monero: return monero!.createMoneroWalletService(_walletInfoSource, _unspentCoinsInfoSource); case WalletType.bitcoin: - return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource); + return bitcoin!.createBitcoinWalletService( + _walletInfoSource, _unspentCoinsInfoSource, + SettingsStoreBase.walletPasswordDirectInput); case WalletType.litecoin: - return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource); + return bitcoin!.createLitecoinWalletService( + _walletInfoSource, _unspentCoinsInfoSource, + SettingsStoreBase.walletPasswordDirectInput); case WalletType.ethereum: - return ethereum!.createEthereumWalletService(_walletInfoSource); + return ethereum!.createEthereumWalletService( + _walletInfoSource, + SettingsStoreBase.walletPasswordDirectInput); default: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } @@ -792,16 +802,19 @@ Future setup({ trades: _tradesSource, settingsStore: getIt.get())); - getIt.registerFactory(() => BackupService(getIt.get(), _walletInfoSource, - getIt.get(), getIt.get())); + getIt.registerFactory(() => BackupService( + getIt.get(), + _walletInfoSource, + getIt.get(), + getIt.get())); getIt.registerFactory(() => BackupViewModel( - getIt.get(), getIt.get(), getIt.get())); + getIt.get(), getIt.get(), getIt.get())); getIt.registerFactory(() => BackupPage(getIt.get())); getIt.registerFactory(() => - EditBackupPasswordViewModel(getIt.get(), getIt.get())); + EditBackupPasswordViewModel(getIt.get(), getIt.get())); getIt.registerFactory(() => EditBackupPasswordPage(getIt.get())); @@ -851,8 +864,7 @@ Future setup({ getIt.registerFactory(() => SupportPage(getIt.get())); getIt.registerFactory(() => - SupportChatPage( - getIt.get(), secureStorage: getIt.get())); + SupportChatPage(getIt.get(), secureStorage: getIt.get())); getIt.registerFactory(() => SupportOtherLinksPage(getIt.get())); @@ -892,7 +904,7 @@ Future setup({ getIt.registerFactory(() => AnyPayApi()); getIt.registerFactory( - () => IoniaService(getIt.get(), getIt.get())); + () => IoniaService(getIt.get(), getIt.get())); getIt.registerFactory(() => IoniaAnyPay( getIt.get(), getIt.get(), getIt.get().wallet!)); @@ -930,7 +942,7 @@ Future setup({ return IoniaVerifyIoniaOtp(getIt.get(), email, isSignIn); }); - getIt.registerFactory(() => IoniaWelcomePage()); + getIt.registerFactory(() => IoniaWelcomePage(getIt.get())); getIt.registerFactoryParam((List args, _) { final merchant = args.first as IoniaMerchant; @@ -1033,6 +1045,65 @@ Future setup({ getIt.registerFactoryParam( (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get())); + getIt.registerFactoryParam((args, _) { + final currentWalletName = getIt + .get() + .getString(PreferencesKey.currentWalletName) ?? ''; + final currentWalletTypeRaw = + getIt.get() + .getInt(PreferencesKey.currentWalletType) ?? 0; + final currentWalletType = deserializeFromInt(currentWalletTypeRaw); + + return WalletUnlockLoadableViewModel( + getIt.get(), + getIt.get(), + walletName: args.walletName ?? currentWalletName, + walletType: args.walletType ?? currentWalletType); + }); + + getIt.registerFactoryParam((args, _) { + final currentWalletName = getIt + .get() + .getString(PreferencesKey.currentWalletName) ?? ''; + final currentWalletTypeRaw = + getIt.get() + .getInt(PreferencesKey.currentWalletType) ?? 0; + final currentWalletType = deserializeFromInt(currentWalletTypeRaw); + + return WalletUnlockVerifiableViewModel( + getIt.get(), + walletName: args.walletName ?? currentWalletName, + walletType: args.walletType ?? currentWalletType); + }); + + getIt.registerFactoryParam((args, closable) { + return WalletUnlockPage( + getIt.get(param1: args), + args.callback, + args.authPasswordHandler, + closable: closable); + }, instanceName: 'wallet_unlock_loadable'); + + getIt.registerFactoryParam((args, closable) { + return WalletUnlockPage( + getIt.get(param1: args), + args.callback, + args.authPasswordHandler, + closable: closable); + }, instanceName: 'wallet_unlock_verifiable'); + + getIt.registerFactory( + () => getIt.get( + param1: WalletUnlockArguments( + callback: (bool successful, _) { + if (successful) { + final authStore = getIt.get(); + authStore.allowed(); + }}), + param2: false, + instanceName: 'wallet_unlock_loadable'), + instanceName: 'wallet_password_login'); + getIt.registerFactoryParam((balanceViewModel, _) => HomeSettingsPage(getIt.get(param1: balanceViewModel))); diff --git a/lib/entities/contact.dart b/lib/entities/contact.dart index cd4fa55a2..e111429ca 100644 --- a/lib/entities/contact.dart +++ b/lib/entities/contact.dart @@ -1,7 +1,8 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:cw_core/keyable.dart'; +import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/utils/mobx.dart'; +import 'package:cw_core/keyable.dart'; part 'contact.g.dart'; @@ -13,7 +14,7 @@ class Contact extends HiveObject with Keyable { } } - static const typeId = CONTACT_TYPE_ID; + static const typeId = 0; static const boxName = 'Contacts'; @HiveField(0, defaultValue: '') diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index b4cb23131..42b6d5324 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:share_plus/share_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -31,7 +31,7 @@ const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; Future defaultSettingsMigration( {required int version, required SharedPreferences sharedPreferences, - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, required Box nodes, required Box walletInfoSource, required Box tradeSource, @@ -392,7 +392,7 @@ Future updateDisplayModes(SharedPreferences sharedPreferences) async { PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode); } -Future generateBackupPassword(FlutterSecureStorage secureStorage) async { +Future generateBackupPassword(SecureStorage secureStorage) async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) { diff --git a/lib/entities/fs_migration.dart b/lib/entities/fs_migration.dart index e3088ff54..ed5503c27 100644 --- a/lib/entities/fs_migration.dart +++ b/lib/entities/fs_migration.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'dart:convert'; import 'package:collection/collection.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:hive/hive.dart'; import 'package:path_provider/path_provider.dart'; @@ -136,9 +136,8 @@ Future ios_migrate_pin() async { return; } - final flutterSecureStorage = FlutterSecureStorage(); - final pinPassword = await flutterSecureStorage.read( - key: 'pin_password', iOptions: IOSOptions()); + final flutterSecureStorage = secureStorageShared; + final pinPassword = await flutterSecureStorage.readNoIOptions(key: 'pin_password'); // No pin if (pinPassword == null) { await prefs.setBool('ios_migration_pin_completed', true); @@ -159,7 +158,7 @@ Future ios_migrate_wallet_passwords() async { } final appDocDir = await getApplicationDocumentsDirectory(); - final flutterSecureStorage = FlutterSecureStorage(); + final flutterSecureStorage = secureStorageShared; final keyService = KeyService(flutterSecureStorage); final walletsDir = Directory('${appDocDir.path}/wallets'); final moneroWalletsDir = Directory('${walletsDir.path}/monero'); @@ -174,8 +173,7 @@ Future ios_migrate_wallet_passwords() async { if (item is Directory) { final name = item.path.split('/').last; final oldKey = 'wallet_monero_' + name + '_password'; - final password = await flutterSecureStorage.read( - key: oldKey, iOptions: IOSOptions()); + final password = await flutterSecureStorage.readNoIOptions(key: oldKey); await keyService.saveWalletPassword( walletName: name, password: password!); } @@ -371,9 +369,8 @@ Future ios_migrate_trades_list(Box tradeSource) async { } final content = file.readAsBytesSync(); - final flutterSecureStorage = FlutterSecureStorage(); - final masterPassword = await flutterSecureStorage.read( - key: 'master_password', iOptions: IOSOptions()); + final flutterSecureStorage = secureStorageShared; + final masterPassword = await flutterSecureStorage.readNoIOptions(key: 'master_password'); final key = masterPassword!.replaceAll('-', ''); final decoded = await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt); diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index e67380bb8..af84bd447 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,18 +1,23 @@ -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:cw_core/cake_hive.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; +import 'package:hive/hive.dart'; Future> getEncryptionKey( - {required String forKey, required FlutterSecureStorage secureStorage}) async { - final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey'); + {required String forKey, required SecureStorage secureStorage}) async { + final stringifiedKey = + await secureStorage.read(key: 'transactionDescriptionsBoxKey'); List key; if (stringifiedKey == null) { - key = CakeHive.generateSecureKey(); + key = Hive.generateSecureKey(); final keyStringified = key.join(','); - await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified); + await secureStorage.write( + key: 'transactionDescriptionsBoxKey', value: keyStringified); } else { - key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); + key = stringifiedKey + .split(',') + .map((i) => int.parse(i)) + .toList(); } return key; -} +} \ No newline at end of file diff --git a/lib/entities/language_service.dart b/lib/entities/language_service.dart index 87ee99ff5..05e84cef9 100644 --- a/lib/entities/language_service.dart +++ b/lib/entities/language_service.dart @@ -55,11 +55,11 @@ class LanguageService { 'cs': 'czk', 'ur': 'pak', 'id': 'idn', - 'yo': 'nga', + 'yo': 'yor', 'ha': 'hau' }; - static final list = {}; + static final list = {}; static void loadLocaleList() { supportedLocales.forEach((key, value) { diff --git a/lib/entities/load_current_wallet.dart b/lib/entities/load_current_wallet.dart index d758b6697..5fedbd016 100644 --- a/lib/entities/load_current_wallet.dart +++ b/lib/entities/load_current_wallet.dart @@ -6,7 +6,7 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; -Future loadCurrentWallet() async { +Future loadCurrentWallet({String? password}) async { final appStore = getIt.get(); final name = getIt .get() @@ -21,7 +21,10 @@ Future loadCurrentWallet() async { final type = deserializeFromInt(typeRaw); final walletLoadingService = getIt.get(); - final wallet = await walletLoadingService.load(type, name); + final wallet = await walletLoadingService.load( + type, + name, + password: password); appStore.changeCurrentWallet(wallet); getIt.get().registerSyncTask(); diff --git a/lib/entities/template.dart b/lib/entities/template.dart index 7cdd2c74a..6955136e0 100644 --- a/lib/entities/template.dart +++ b/lib/entities/template.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'template.g.dart'; @@ -15,7 +14,7 @@ class Template extends HiveObject { required this.amountFiatRaw, this.additionalRecipientsRaw}); - static const typeId = TEMPLATE_TYPE_ID; + static const typeId = 6; static const boxName = 'Template'; @HiveField(0) diff --git a/lib/entities/transaction_description.dart b/lib/entities/transaction_description.dart index 088f9c480..86d6b043a 100644 --- a/lib/entities/transaction_description.dart +++ b/lib/entities/transaction_description.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'transaction_description.g.dart'; @@ -7,7 +6,7 @@ part 'transaction_description.g.dart'; class TransactionDescription extends HiveObject { TransactionDescription({required this.id, this.recipientAddress, this.transactionNote}); - static const typeId = TRANSACTION_TYPE_ID; + static const typeId = 2; static const boxName = 'TransactionDescriptions'; static const boxKey = 'transactionDescriptionsBoxKey'; diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index f2db7741e..cb13b30d2 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -4,15 +4,16 @@ class CWEthereum extends Ethereum { @override List getEthereumWordList(String language) => EthereumMnemonics.englishWordlist; - WalletService createEthereumWalletService(Box walletInfoSource) => - EthereumWalletService(walletInfoSource); + WalletService createEthereumWalletService(Box walletInfoSource, bool isDirect) => + EthereumWalletService(walletInfoSource, isDirect); @override WalletCredentials createEthereumNewWalletCredentials({ required String name, WalletInfo? walletInfo, + String? password, }) => - EthereumNewWalletCredentials(name: name, walletInfo: walletInfo); + EthereumNewWalletCredentials(name: name, walletInfo: walletInfo, password: password); @override WalletCredentials createEthereumRestoreWalletFromSeedCredentials({ diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/changenow/changenow_exchange_provider.dart index 6166a8875..da4e7eccb 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/changenow/changenow_exchange_provider.dart @@ -202,11 +202,11 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final expectedSendAmount = responseJSON['expectedAmountFrom'].toString(); final status = responseJSON['status'] as String; final state = TradeState.deserialize(raw: status); - final extraId = responseJSON['payinExtraId'] as String?; - final outputTransaction = responseJSON['payoutHash'] as String?; - final expiredAtRaw = responseJSON['validUntil'] as String?; + final extraId = responseJSON['payinExtraId'] as String; + final outputTransaction = responseJSON['payoutHash'] as String; + final expiredAtRaw = responseJSON['validUntil'] as String; final payoutAddress = responseJSON['payoutAddress'] as String; - final expiredAt = DateTime.tryParse(expiredAtRaw ?? '')?.toLocal(); + final expiredAt = DateTime.tryParse(expiredAtRaw)?.toLocal(); return Trade( id: id, diff --git a/lib/exchange/exchange_template.dart b/lib/exchange/exchange_template.dart index 2182efd8c..dcfd8d8e8 100644 --- a/lib/exchange/exchange_template.dart +++ b/lib/exchange/exchange_template.dart @@ -1,4 +1,3 @@ -import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'exchange_template.g.dart'; @@ -15,7 +14,7 @@ class ExchangeTemplate extends HiveObject { required this.depositCurrencyTitleRaw, required this.receiveCurrencyTitleRaw}); - static const typeId = EXCHANGE_TEMPLATE_TYPE_ID; + static const typeId = 7; static const boxName = 'ExchangeTemplate'; @HiveField(0) diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 257d339cf..884899e54 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -19,10 +19,10 @@ class SideShiftExchangeProvider extends ExchangeProvider { static const affiliateId = secrets.sideShiftAffiliateId; static const apiBaseUrl = 'https://sideshift.ai/api'; - static const rangePath = '/v2/pair'; - static const orderPath = '/v2/shifts'; - static const quotePath = '/v2/quotes'; - static const permissionPath = '/v2/permissions'; + static const rangePath = '/v1/pairs'; + static const orderPath = '/v1/orders'; + static const quotePath = '/v1/quotes'; + static const permissionPath = '/v1/permissions'; static const List _notSupported = [ CryptoCurrency.xhv, @@ -35,22 +35,23 @@ class SideShiftExchangeProvider extends ExchangeProvider { CryptoCurrency.scrt, CryptoCurrency.stx, CryptoCurrency.bttc, - CryptoCurrency.usdt, - CryptoCurrency.eos, ]; static List _supportedPairs() { - final supportedCurrencies = - CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList(); + final supportedCurrencies = CryptoCurrency.all + .where((element) => !_notSupported.contains(element)) + .toList(); return supportedCurrencies - .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) + .map((i) => supportedCurrencies + .map((k) => ExchangePair(from: i, to: k, reverse: true))) .expand((i) => i) .toList(); } @override - ExchangeProviderDescription get description => ExchangeProviderDescription.sideShift; + ExchangeProviderDescription get description => + ExchangeProviderDescription.sideShift; @override Future fetchRate( @@ -63,18 +64,17 @@ class SideShiftExchangeProvider extends ExchangeProvider { if (amount == 0) { return 0.0; } - - final fromCurrency = from.title.toLowerCase(); - final toCurrency = to.title.toLowerCase(); - final depositNetwork = _networkFor(from); - final settleNetwork = _networkFor(to); - - final url = "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork"; - + final fromCurrency = _normalizeCryptoCurrency(from); + final toCurrency = _normalizeCryptoCurrency(to); + final url = + apiBaseUrl + rangePath + '/' + fromCurrency + '/' + toCurrency; final uri = Uri.parse(url); final response = await get(uri); final responseJSON = json.decode(response.body) as Map; final rate = double.parse(responseJSON['rate'] as String); + final max = double.parse(responseJSON['max'] as String); + + if (amount > max) return 0.00; return rate; } catch (_) { @@ -100,38 +100,25 @@ class SideShiftExchangeProvider extends ExchangeProvider { } final responseJSON = json.decode(response.body) as Map; - final cancreateShift = responseJSON['createShift'] as bool; - return cancreateShift; + final canCreateOrder = responseJSON['createOrder'] as bool; + final canCreateQuote = responseJSON['createQuote'] as bool; + return canCreateOrder && canCreateQuote; } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + Future createTrade( + {required TradeRequest request, required bool isFixedRateMode}) async { final _request = request as SideShiftRequest; - String url = ''; - final depositCoin = request.depositMethod.title.toLowerCase(); - final settleCoin = request.settleMethod.title.toLowerCase(); + final quoteId = await _createQuote(_request); + final url = apiBaseUrl + orderPath; + final headers = {'Content-Type': 'application/json'}; final body = { + 'type': 'fixed', + 'quoteId': quoteId, 'affiliateId': affiliateId, 'settleAddress': _request.settleAddress, - 'refundAddress': _request.refundAddress, + 'refundAddress': _request.refundAddress }; - - if (isFixedRateMode) { - final quoteId = await _createQuote(_request); - body['quoteId'] = quoteId; - - url = apiBaseUrl + orderPath + '/fixed'; - } else { - url = apiBaseUrl + orderPath + '/variable'; - final depositNetwork = _networkFor(request.depositMethod); - final settleNetwork = _networkFor(request.settleMethod); - body["depositCoin"] = depositCoin; - body["settleCoin"] = settleCoin; - body["settleNetwork"] = settleNetwork; - body["depositNetwork"] = depositNetwork; - } - final headers = {'Content-Type': 'application/json'}; - final uri = Uri.parse(url); final response = await post(uri, headers: headers, body: json.encode(body)); @@ -148,9 +135,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final id = responseJSON['id'] as String; - final inputAddress = responseJSON['depositAddress'] as String; - final settleAddress = responseJSON['settleAddress'] as String; - final depositAmount = responseJSON['depositAmount'] as String?; + final inputAddress = responseJSON['depositAddress']['address'] as String; + final settleAddress = responseJSON['settleAddress']['address'] as String; return Trade( id: id, @@ -160,7 +146,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { inputAddress: inputAddress, refundAddress: settleAddress, state: TradeState.created, - amount: depositAmount ?? _request.depositAmount, + amount: _request.depositAmount, payoutAddress: settleAddress, createdAt: DateTime.now(), ); @@ -169,17 +155,13 @@ class SideShiftExchangeProvider extends ExchangeProvider { Future _createQuote(SideShiftRequest request) async { final url = apiBaseUrl + quotePath; final headers = {'Content-Type': 'application/json'}; - final depositMethod = request.depositMethod.title.toLowerCase(); - final settleMethod = request.settleMethod.title.toLowerCase(); - final depositNetwork = _networkFor(request.depositMethod); - final settleNetwork = _networkFor(request.settleMethod); + final depositMethod = _normalizeCryptoCurrency(request.depositMethod); + final settleMethod = _normalizeCryptoCurrency(request.settleMethod); final body = { - 'depositCoin': depositMethod, - 'settleCoin': settleMethod, + 'depositMethod': depositMethod, + 'settleMethod': settleMethod, 'affiliateId': affiliateId, - 'settleAmount': request.depositAmount, - 'settleNetwork': settleNetwork, - 'depositNetwork': depositNetwork, + 'depositAmount': request.depositAmount, }; final uri = Uri.parse(url); final response = await post(uri, headers: headers, body: json.encode(body)); @@ -206,15 +188,9 @@ class SideShiftExchangeProvider extends ExchangeProvider { {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode}) async { - final fromCurrency = isFixedRateMode ? to : from; - final toCurrency = isFixedRateMode ? from : to; - - final fromNetwork = _networkFor(fromCurrency); - final toNetwork = _networkFor(toCurrency); - - final url = - "$apiBaseUrl$rangePath/${fromCurrency.title.toLowerCase()}-$fromNetwork/${toCurrency.title.toLowerCase()}-$toNetwork"; - + final fromCurrency = _normalizeCryptoCurrency(from); + final toCurrency = _normalizeCryptoCurrency(to); + final url = apiBaseUrl + rangePath + '/' + fromCurrency + '/' + toCurrency; final uri = Uri.parse(url); final response = await get(uri); @@ -233,14 +209,6 @@ class SideShiftExchangeProvider extends ExchangeProvider { final min = double.tryParse(responseJSON['min'] as String? ?? ''); final max = double.tryParse(responseJSON['max'] as String? ?? ''); - if (isFixedRateMode) { - final currentRate = double.parse(responseJSON['rate'] as String); - return Limits( - min: min != null ? (min * currentRate) : null, - max: max != null ? (max * currentRate) : null, - ); - } - return Limits(min: min, max: max); } @@ -258,7 +226,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final error = responseJSON['error']['message'] as String; - throw TradeNotFoundException(id, provider: description, description: error); + throw TradeNotFoundException(id, + provider: description, description: error); } if (response.statusCode != 200) { @@ -266,32 +235,36 @@ class SideShiftExchangeProvider extends ExchangeProvider { } final responseJSON = json.decode(response.body) as Map; - final fromCurrency = responseJSON['depositCoin'] as String; + final fromCurrency = responseJSON['depositMethodId'] as String; final from = CryptoCurrency.fromString(fromCurrency); - final toCurrency = responseJSON['settleCoin'] as String; + final toCurrency = responseJSON['settleMethodId'] as String; final to = CryptoCurrency.fromString(toCurrency); - final inputAddress = responseJSON['depositAddress'] as String; - final expectedSendAmount = responseJSON['depositAmount'] as String?; - final status = responseJSON['status'] as String?; - final settleAddress = responseJSON['settleAddress'] as String; + final inputAddress = responseJSON['depositAddress']['address'] as String; + final expectedSendAmount = responseJSON['depositAmount'].toString(); + final deposits = responseJSON['deposits'] as List?; + final settleAddress = responseJSON['settleAddress']['address'] as String; TradeState? state; + String? status; + if (deposits?.isNotEmpty ?? false) { + status = deposits![0]['status'] as String?; + } state = TradeState.deserialize(raw: status ?? 'created'); - final isVariable = (responseJSON['type'] as String) == 'variable'; - final expiredAtRaw = responseJSON['expiresAt'] as String; - final expiredAt = isVariable ? null : DateTime.tryParse(expiredAtRaw)?.toLocal(); + final expiredAtRaw = responseJSON['expiresAtISO'] as String; + final expiredAt = DateTime.tryParse(expiredAtRaw)?.toLocal(); return Trade( - id: id, - from: from, - to: to, - provider: description, - inputAddress: inputAddress, - amount: expectedSendAmount ?? '', - state: state, - expiredAt: expiredAt, - payoutAddress: settleAddress); + id: id, + from: from, + to: to, + provider: description, + inputAddress: inputAddress, + amount: expectedSendAmount, + state: state, + expiredAt: expiredAt, + payoutAddress: settleAddress + ); } @override @@ -306,25 +279,28 @@ class SideShiftExchangeProvider extends ExchangeProvider { @override String get title => 'SideShift'; - String _networkFor(CryptoCurrency currency) => - currency.tag != null ? _normalizeTag(currency.tag!) : 'mainnet'; - - String _normalizeTag(String tag) { - switch (tag) { - case 'ETH': - return 'ethereum'; - case 'TRX': - return 'tron'; - case 'LN': - return 'lightning'; - case 'POLY': + static String _normalizeCryptoCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.zaddr: + return 'zaddr'; + case CryptoCurrency.zec: + return 'zec'; + case CryptoCurrency.bnb: + return currency.tag!.toLowerCase(); + case CryptoCurrency.usdterc20: + return 'usdtErc20'; + case CryptoCurrency.usdttrc20: + return 'usdtTrc20'; + case CryptoCurrency.usdcpoly: + return 'usdcpolygon'; + case CryptoCurrency.usdcsol: + return 'usdcsol'; + case CryptoCurrency.maticpoly: return 'polygon'; - case 'ZEC': - return 'zcash'; - case 'AVAXC': - return 'avax'; + case CryptoCurrency.btcln: + return 'ln'; default: - return tag.toLowerCase(); + return currency.title.toLowerCase(); } } } diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index db8c8fb3b..70dfa5713 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -1,9 +1,8 @@ +import 'package:hive/hive.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/hive_type_ids.dart'; -import 'package:hive/hive.dart'; part 'trade.g.dart'; @@ -42,7 +41,7 @@ class Trade extends HiveObject { } } - static const typeId = TRADE_TYPE_ID; + static const typeId = 3; static const boxName = 'Trades'; static const boxKey = 'tradesBoxKey'; diff --git a/lib/ionia/ionia_service.dart b/lib/ionia/ionia_service.dart index 51e23ad28..9d4deeaf8 100644 --- a/lib/ionia/ionia_service.dart +++ b/lib/ionia/ionia_service.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/ionia/ionia_order.dart'; import 'package:cake_wallet/ionia/ionia_virtual_card.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; @@ -17,7 +17,7 @@ class IoniaService { static String get clientId => secrets.ioniaClientId; - final FlutterSecureStorage secureStorage; + final SecureStorage secureStorage; final IoniaApi ioniaApi; // Create user diff --git a/lib/main.dart b/lib/main.dart index db5335ac1..8ade81e3e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,7 +7,8 @@ import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cw_core/hive_type_ids.dart'; +import 'package:cw_core/root_dir.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -15,7 +16,7 @@ import 'package:hive/hive.dart'; import 'package:cake_wallet/di.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/router.dart' as Router; @@ -39,7 +40,6 @@ import 'package:uni_links/uni_links.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/cake_hive.dart'; final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); @@ -58,8 +58,7 @@ Future main() async { return true; }; - - await CakeHive.close(); + await Hive.close(); await initializeAppConfigs(); @@ -70,70 +69,71 @@ Future main() async { } Future initializeAppConfigs() async { - final appDir = await getApplicationDocumentsDirectory(); - CakeHive.init(appDir.path); + setRootDirFromEnv(); + final appDir = await getAppDir(); + Hive.init(appDir.path); - if (!CakeHive.isAdapterRegistered(Contact.typeId)) { - CakeHive.registerAdapter(ContactAdapter()); + if (!Hive.isAdapterRegistered(Contact.typeId)) { + Hive.registerAdapter(ContactAdapter()); } - if (!CakeHive.isAdapterRegistered(Node.typeId)) { - CakeHive.registerAdapter(NodeAdapter()); + if (!Hive.isAdapterRegistered(Node.typeId)) { + Hive.registerAdapter(NodeAdapter()); } - if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) { - CakeHive.registerAdapter(TransactionDescriptionAdapter()); + if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) { + Hive.registerAdapter(TransactionDescriptionAdapter()); } - if (!CakeHive.isAdapterRegistered(Trade.typeId)) { - CakeHive.registerAdapter(TradeAdapter()); + if (!Hive.isAdapterRegistered(Trade.typeId)) { + Hive.registerAdapter(TradeAdapter()); } - if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { - CakeHive.registerAdapter(WalletInfoAdapter()); + if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { + Hive.registerAdapter(WalletInfoAdapter()); } - if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { - CakeHive.registerAdapter(WalletTypeAdapter()); + if (!Hive.isAdapterRegistered(walletTypeTypeId)) { + Hive.registerAdapter(WalletTypeAdapter()); } - if (!CakeHive.isAdapterRegistered(Template.typeId)) { - CakeHive.registerAdapter(TemplateAdapter()); + if (!Hive.isAdapterRegistered(Template.typeId)) { + Hive.registerAdapter(TemplateAdapter()); } - if (!CakeHive.isAdapterRegistered(ExchangeTemplate.typeId)) { - CakeHive.registerAdapter(ExchangeTemplateAdapter()); + if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) { + Hive.registerAdapter(ExchangeTemplateAdapter()); } - if (!CakeHive.isAdapterRegistered(Order.typeId)) { - CakeHive.registerAdapter(OrderAdapter()); + if (!Hive.isAdapterRegistered(Order.typeId)) { + Hive.registerAdapter(OrderAdapter()); } - if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { - CakeHive.registerAdapter(UnspentCoinsInfoAdapter()); + if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { + Hive.registerAdapter(UnspentCoinsInfoAdapter()); } - if (!CakeHive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { - CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); + if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { + Hive.registerAdapter(AnonpayInvoiceInfoAdapter()); } - final secureStorage = FlutterSecureStorage(); - final transactionDescriptionsBoxKey = - await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey); - final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey); - final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey); - final contacts = await CakeHive.openBox(Contact.boxName); - final nodes = await CakeHive.openBox(Node.boxName); - final transactionDescriptions = await CakeHive.openBox( - 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); - final templates = await CakeHive.openBox