From e39d5c6af4461946007dfe68b2cbcbdbd9c33c86 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 6 Sep 2023 17:44:55 -0300 Subject: [PATCH] Merge main into cw-linux --- .github/workflows/cache_dependencies.yml | 3 +- .github/workflows/pr_test_build.yml | 12 +- assets/text/Monerocom_Release_Notes.txt | 7 +- assets/text/Release_Notes.txt | 8 +- cw_bitcoin/pubspec.lock | 56 ++-- cw_core/lib/address_info.dart | 21 ++ 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/wallet_addresses.dart | 10 +- cw_core/lib/wallet_base.dart | 4 + cw_core/lib/wallet_info.dart | 11 +- cw_core/pubspec.lock | 307 +++++++++++------- cw_ethereum/lib/ethereum_wallet.dart | 14 +- cw_ethereum/lib/ethereum_wallet_service.dart | 1 + cw_haven/lib/haven_wallet.dart | 82 ++--- cw_haven/pubspec.lock | 42 +-- cw_monero/example/pubspec.lock | 42 +-- cw_monero/ios/Classes/monero_api.cpp | 14 +- cw_monero/lib/monero_subaddress_list.dart | 88 ++++- cw_monero/lib/monero_wallet.dart | 37 ++- cw_monero/lib/monero_wallet_addresses.dart | 51 ++- cw_monero/lib/monero_wallet_service.dart | 21 +- cw_monero/macos/Classes/monero_api.cpp | 203 +++++++++++- cw_monero/pubspec.lock | 42 +-- ios/Podfile.lock | 23 -- ios/Runner.xcodeproj/project.pbxproj | 1 + lib/core/backup_service.dart | 6 + lib/core/fiat_conversion_service.dart | 8 +- lib/di.dart | 2 +- .../auto_generate_subaddress_status.dart | 13 + lib/entities/default_settings_migration.dart | 76 ++++- lib/entities/preferences_key.dart | 1 + lib/main.dart | 90 ++--- lib/reactions/on_current_wallet_change.dart | 81 +++-- .../desktop_dashboard_actions.dart | 10 +- .../dashboard/widgets/address_page.dart | 41 ++- .../dashboard/widgets/market_place_page.dart | 18 +- .../monero_accounts/widgets/account_tile.dart | 15 +- .../screens/restore/restore_options_page.dart | 2 +- .../restore/widgets/backup_file_button.dart | 0 .../settings/display_settings_page.dart | 112 ++++--- .../screens/settings/manage_nodes_page.dart | 58 ++-- lib/src/screens/settings/privacy_page.dart | 8 + .../support/widgets/support_tiles.dart | 3 +- lib/src/widgets/search_bar_widget.dart | 2 +- lib/store/settings_store.dart | 37 ++- .../contact_list/contact_list_view_model.dart | 31 +- .../dashboard/dashboard_view_model.dart | 5 + .../node_list/node_list_view_model.dart | 1 + .../settings/privacy_settings_view_model.dart | 22 +- .../unspent_coins_list_view_model.dart | 2 - macos/Podfile.lock | 8 +- model_generator.sh | 12 +- res/values/strings_ar.arb | 2 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- scripts/android/app_env.sh | 8 +- scripts/android/build_haven.sh | 2 +- scripts/ios/app_env.sh | 8 +- scripts/linux/app_env.sh | 4 +- scripts/macos/app_env.sh | 4 +- tool/append_translation.dart | 54 +-- tool/translation_consistence.dart | 37 +++ tool/utils/translation/arb_file_utils.dart | 66 ++++ .../translation/translation_constants.dart | 6 + tool/utils/translation/translation_utils.dart | 37 +++ 89 files changed, 1400 insertions(+), 654 deletions(-) create mode 100644 cw_core/lib/address_info.dart create mode 100644 cw_core/lib/cake_hive.dart create mode 100644 cw_core/lib/hive_type_ids.dart create mode 100644 lib/entities/auto_generate_subaddress_status.dart create mode 100644 lib/src/screens/restore/widgets/backup_file_button.dart create mode 100644 tool/translation_consistence.dart create mode 100644 tool/utils/translation/arb_file_utils.dart create mode 100644 tool/utils/translation/translation_constants.dart create mode 100644 tool/utils/translation/translation_utils.dart diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index d57281447..5373bbc87 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -1,6 +1,7 @@ name: Cache Dependencies on: + workflow_dispatch: push: branches: [ main ] @@ -45,7 +46,7 @@ jobs: /opt/android/cake_wallet/cw_monero/android/.cxx /opt/android/cake_wallet/cw_monero/ios/External /opt/android/cake_wallet/cw_shared_external/ios/External - key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }} + key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh', '**/monero_api.cpp') }} - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 80d5d74aa..30bf3058e 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -163,7 +163,11 @@ jobs: - name: Send Test APK continue-on-error: true - run: | - cd /opt/android/cake_wallet - var=$(curl --upload-file build/app/outputs/apk/release/app-release.apk https://transfer.sh/$GITHUB_HEAD_REF.apk -H "Max-Days: 10") - curl ${{ secrets.SLACK_WEB_HOOK }} -H "Content-Type: application/json" -d '{"apk_link": "'"$var"'","ticket": "'"$GITHUB_HEAD_REF"'"}' + uses: adrey/slack-file-upload-action@1.0.5 + with: + token: ${{ secrets.SLACK_APP_TOKEN }} + path: /opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk + channel: ${{ secrets.SLACK_APK_CHANNEL }} + title: '${{github.head_ref}}.apk' + filename: ${{github.head_ref}}.apk + initial_comment: ${{ github.event.head_commit.message }} diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 62f649704..a8b55383d 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1,5 @@ -Bug fixes -Fiat Onramp improvements \ No newline at end of file +Ability to Auto generate new Monero subaddress when used +Coin Control for Monero +In-app Live Chat support +Additional themes +Bug Fixes and performance enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 62f649704..263689318 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,2 +1,6 @@ -Bug fixes -Fiat Onramp improvements \ No newline at end of file +Restore Ethereum from private key and QR +Ability to Auto generate new Monero subaddress when used +Coin Control for Monero +In-app Live Chat support +Additional themes +Bug Fixes and performance enhancements \ No newline at end of file diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 4bce06bab..fe8b55acd 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -37,19 +37,19 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" bech32: dependency: transitive description: path: "." - ref: "cake-0.2.1" - resolved-ref: cafd1c270641e95017d57d69f55cca9831d4db56 + ref: "cake-0.2.2" + resolved-ref: "05755063b593aa6cca0a4820a318e0ce17de6192" url: "https://github.com/cake-tech/bech32.git" source: git - version: "0.2.1" + version: "0.2.2" bip32: dependency: transitive description: @@ -70,8 +70,8 @@ packages: dependency: "direct main" description: path: "." - ref: cake-update-v2 - resolved-ref: "8f86453761c0c26e368392d0ff2c6f12f3b7397b" + ref: cake-update-v3 + resolved-ref: df9204144011ed9419eff7d9ef3143102a40252d url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git version: "2.0.2" @@ -168,10 +168,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -200,18 +200,18 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.1" crypto: dependency: transitive description: @@ -361,10 +361,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -385,10 +385,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -401,10 +401,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -425,10 +425,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -441,10 +441,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -481,10 +481,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -686,10 +686,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -771,5 +771,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_core/lib/address_info.dart b/cw_core/lib/address_info.dart new file mode 100644 index 000000000..63dc023ab --- /dev/null +++ b/cw_core/lib/address_info.dart @@ -0,0 +1,21 @@ +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; + +part 'address_info.g.dart'; + +@HiveType(typeId: ADDRESS_INFO_TYPE_ID) +class AddressInfo extends HiveObject { + AddressInfo({required this.address, this.accountIndex, required this.label}); + + static const typeId = ADDRESS_INFO_TYPE_ID; + static const boxName = 'AddressInfo'; + + @HiveField(0) + int? accountIndex; + + @HiveField(1, defaultValue: '') + String address; + + @HiveField(2, defaultValue: '') + String label; +} diff --git a/cw_core/lib/cake_hive.dart b/cw_core/lib/cake_hive.dart new file mode 100644 index 000000000..aadf6bf9a --- /dev/null +++ b/cw_core/lib/cake_hive.dart @@ -0,0 +1,4 @@ +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 db5b6db5b..fd27aaba6 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -1,4 +1,5 @@ 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'; @@ -53,7 +54,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { iconPath: icon, ); - static const typeId = 12; + static const typeId = ERC20_TOKEN_TYPE_ID; static const boxName = 'Erc20Tokens'; @override diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart new file mode 100644 index 000000000..950f39e1f --- /dev/null +++ b/cw_core/lib/hive_type_ids.dart @@ -0,0 +1,13 @@ +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 ADDRESS_INFO_TYPE_ID = 11; +const ERC20_TOKEN_TYPE_ID = 12; diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index a34101a88..27b5468c5 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -1,8 +1,10 @@ +import 'package:cw_core/address_info.dart'; import 'package:cw_core/wallet_info.dart'; abstract class WalletAddresses { WalletAddresses(this.walletInfo) - : addressesMap = {}; + : addressesMap = {}, + addressInfos = {}; final WalletInfo walletInfo; @@ -12,6 +14,10 @@ abstract class WalletAddresses { Map addressesMap; + Map> addressInfos; + + Set usedAddresses = {}; + Future init(); Future updateAddressesInBox(); @@ -20,6 +26,8 @@ abstract class WalletAddresses { try { walletInfo.address = address; walletInfo.addresses = addressesMap; + walletInfo.addressInfos = addressInfos; + walletInfo.usedAddresses = usedAddresses.toList(); if (walletInfo.isInBox) { await walletInfo.save(); diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 3f6b57edc..cefc3c2fa 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -52,6 +52,10 @@ abstract class WalletBase< late HistoryType transactionHistory; + set isEnabledAutoGenerateSubaddress(bool value) {} + + bool get isEnabledAutoGenerateSubaddress => false; + Future connectToNode({required Node node}); Future startSync(); diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index a25702cf7..ddd15e851 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,7 +1,8 @@ -import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:cw_core/wallet_type.dart'; import 'dart:async'; +import 'package:cw_core/address_info.dart'; +import 'package:cw_core/hive_type_ids.dart'; part 'wallet_info.g.dart'; @@ -30,7 +31,7 @@ class WalletInfo extends HiveObject { yatEid, yatLastUsedAddressRaw, showIntroCakePayCard); } - static const typeId = 4; + static const typeId = WALLET_INFO_TYPE_ID; static const boxName = 'WalletInfo'; @HiveField(0, defaultValue: '') @@ -72,6 +73,12 @@ class WalletInfo extends HiveObject { @HiveField(13) bool? showIntroCakePayCard; + @HiveField(14) + Map>? addressInfos; + + @HiveField(15) + List? usedAddresses; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index b0fb67435..e399526fd 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -5,191 +5,218 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + url: "https://pub.dev" source: hosted version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + url: "https://pub.dev" source: hosted version: "4.7.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.3.2" asn1lib: dependency: transitive description: name: asn1lib - url: "https://pub.dartlang.org" + sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + url: "https://pub.dev" source: hosted version: "1.4.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.0" build_resolvers: dependency: "direct dev" description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + url: "https://pub.dev" source: hosted version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" source: hosted version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + url: "https://pub.dev" source: hosted - version: "8.4.4" + version: "8.4.3" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted version: "2.0.2" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" source: hosted version: "4.4.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted version: "3.1.1" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" source: hosted version: "2.2.4" encrypt: dependency: "direct main" description: name: encrypt - url: "https://pub.dartlang.org" + sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + url: "https://pub.dev" source: hosted version: "5.0.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" file: dependency: "direct main" description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted version: "6.1.4" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -199,7 +226,8 @@ packages: dependency: "direct main" description: name: flutter_mobx - url: "https://pub.dartlang.org" + sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + url: "https://pub.dev" source: hosted version: "2.0.6+5" flutter_test: @@ -211,252 +239,288 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted version: "3.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted version: "2.1.1" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + url: "https://pub.dev" source: hosted version: "2.2.0" hive: dependency: transitive description: name: hive - url: "https://pub.dartlang.org" + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" source: hosted version: "2.2.3" hive_generator: dependency: "direct dev" description: name: hive_generator - url: "https://pub.dartlang.org" + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" + url: "https://pub.dev" source: hosted version: "1.1.3" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" intl: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted version: "4.8.0" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted version: "1.0.4" mobx: dependency: "direct main" description: name: mobx - url: "https://pub.dartlang.org" + sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.3+1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - url: "https://pub.dartlang.org" + sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + url: "https://pub.dev" source: hosted version: "2.1.1" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" source: hosted - version: "2.0.24" + version: "2.0.22" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - url: "https://pub.dartlang.org" + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted - version: "2.1.10" + version: "2.1.7" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.3" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.3" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + url: "https://pub.dev" source: hosted version: "3.6.2" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.2.1" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted version: "1.4.0" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted version: "1.0.3" sky_engine: @@ -468,121 +532,138 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + url: "https://pub.dev" source: hosted version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - url: "https://pub.dartlang.org" + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + url: "https://pub.dev" source: hosted version: "1.3.3" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.5.1" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted version: "1.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted version: "2.3.0" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" source: hosted version: "3.1.3" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "0.2.0+3" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index d8c236657..e36e1ee87 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -4,6 +4,7 @@ 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'; @@ -61,14 +62,11 @@ abstract class EthereumWalletBase {CryptoCurrency.eth: initialBalance ?? ERC20Balance(BigInt.zero)}), super(walletInfo) { this.walletInfo = walletInfo; - transactionHistory = EthereumTransactionHistory( - walletInfo: walletInfo, - password: password, - encryptionFileUtils: encryptionFileUtils, - ); + transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password, encryptionFileUtils: encryptionFileUtils, +); - if (!Hive.isAdapterRegistered(Erc20Token.typeId)) { - Hive.registerAdapter(Erc20TokenAdapter()); + if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { + CakeHive.registerAdapter(Erc20TokenAdapter()); } _sharedPrefs.complete(SharedPreferences.getInstance()); @@ -107,7 +105,7 @@ abstract class EthereumWalletBase Completer _sharedPrefs = Completer(); Future init() async { - erc20TokensBox = await Hive.openBox(Erc20Token.boxName); + erc20TokensBox = await CakeHive.openBox(Erc20Token.boxName); await walletAddresses.init(); await transactionHistory.init(); _ethPrivateKey = await getPrivateKey( diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 66066b996..289e7d25b 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -75,6 +75,7 @@ class EthereumWalletService extends WalletService with Store { +abstract class HavenWalletBase + extends WalletBase with Store { HavenWalletBase({required WalletInfo walletInfo}) : balance = ObservableMap.of(getHavenBalance(accountIndex: 0)), _isTransactionUpdating = false, @@ -47,8 +46,7 @@ abstract class HavenWalletBase extends WalletBase walletAddresses.account, - (Account? account) { + _onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) { if (account == null) { return; } @@ -96,14 +94,12 @@ abstract class HavenWalletBase extends WalletBase await save()); + _autoSaveTimer = + Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save()); } @override @@ -115,7 +111,7 @@ abstract class HavenWalletBase extends WalletBase connectToNode({required Node node}) async { try { @@ -170,26 +166,25 @@ abstract class HavenWalletBase extends WalletBase item.sendAll - || (item.formattedCryptoAmount ?? 0) <= 0)) { - throw HavenTransactionCreationException('You do not have enough coins to send this amount.'); + if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + throw HavenTransactionCreationException( + 'You do not have enough coins to send this amount.'); } - final int totalAmount = outputs.fold(0, (acc, value) => - acc + (value.formattedCryptoAmount ?? 0)); + final int totalAmount = + outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)); if (unlockedBalance < totalAmount) { - throw HavenTransactionCreationException('You do not have enough coins to send this amount.'); + throw HavenTransactionCreationException( + 'You do not have enough coins to send this amount.'); } - final moneroOutputs = outputs.map((output) => - MoneroOutput( - address: output.address, - amount: output.cryptoAmount!.replaceAll(',', '.'))) + final moneroOutputs = outputs + .map((output) => MoneroOutput( + address: output.address, amount: output.cryptoAmount!.replaceAll(',', '.'))) .toList(); - pendingTransactionDescription = - await transaction_history.createTransactionMultDest( + pendingTransactionDescription = await transaction_history.createTransactionMultDest( outputs: moneroOutputs, priorityRaw: _credentials.priority.serialize(), accountIndex: walletAddresses.account!.id); @@ -198,12 +193,8 @@ abstract class HavenWalletBase extends WalletBase - haven_wallet.getAddress( - accountIndex: accountIndex, - addressIndex: addressIndex); + haven_wallet.getAddress(accountIndex: accountIndex, addressIndex: addressIndex); @override Future> fetchTransactions() async { haven_transaction_history.refreshTransactions(); - return _getAllTransactions(null).fold>( - {}, - (Map acc, HavenTransactionInfo tx) { + return _getAllTransactions(null) + .fold>({}, + (Map acc, HavenTransactionInfo tx) { acc[tx.id] = tx; return acc; }); @@ -340,9 +328,9 @@ abstract class HavenWalletBase extends WalletBase _getAllTransactions(dynamic _) => haven_transaction_history - .getAllTransations() - .map((row) => HavenTransactionInfo.fromRow(row)) - .toList(); + .getAllTransations() + .map((row) => HavenTransactionInfo.fromRow(row)) + .toList(); void _setListeners() { _listener?.stop(); @@ -364,8 +352,7 @@ abstract class HavenWalletBase extends WalletBase balance.addAll(getHavenBalance(accountIndex: walletAddresses.account!.id)); - Future _askForUpdateTransactionHistory() async => - await updateTransactions(); + Future _askForUpdateTransactionHistory() async => await updateTransactions(); void _onNewBlock(int height, int blocksLeft, double ptc) async { try { @@ -404,9 +390,9 @@ abstract class HavenWalletBase extends WalletBase=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index f4c36e69c..1aae6b0c9 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_parser: dependency: transitive description: @@ -173,18 +173,18 @@ packages: dependency: transitive description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" lints: dependency: transitive description: @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mobx: dependency: transitive description: @@ -229,10 +229,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: transitive description: @@ -362,10 +362,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" typed_data: dependency: transitive description: @@ -399,5 +399,5 @@ packages: source: hosted version: "0.2.0+3" sdks: - dart: ">=2.18.1 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index d81907813..010763bc2 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -145,7 +145,7 @@ extern "C" int8_t direction; int8_t isPending; uint32_t subaddrIndex; - + char *hash; char *paymentId; @@ -161,7 +161,7 @@ extern "C" std::set::iterator it = subIndex.begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); - datetime = static_cast(transaction->timestamp()); + datetime = static_cast(transaction->timestamp()); direction = transaction->direction(); isPending = static_cast(transaction->isPending()); std::string *hash_str = new std::string(transaction->hash()); @@ -241,7 +241,7 @@ extern "C" } void setUnlocked(bool unlocked); - + }; Monero::Coins *m_coins; @@ -262,7 +262,7 @@ extern "C" { m_wallet = wallet; m_listener = nullptr; - + if (wallet != nullptr) { @@ -505,7 +505,7 @@ extern "C" { nice(19); Monero::Wallet *wallet = get_current_wallet(); - + std::string _login = ""; std::string _password = ""; std::string _socksProxyAddress = ""; @@ -601,7 +601,7 @@ extern "C" _preferred_inputs.insert(std::string(*preferred_inputs)); preferred_inputs++; } - + auto priority = static_cast(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -620,7 +620,7 @@ extern "C" { transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } - + int status = transaction->status(); if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical) diff --git a/cw_monero/lib/monero_subaddress_list.dart b/cw_monero/lib/monero_subaddress_list.dart index 0dcddc679..09807e7cd 100644 --- a/cw_monero/lib/monero_subaddress_list.dart +++ b/cw_monero/lib/monero_subaddress_list.dart @@ -6,14 +6,15 @@ import 'package:cw_core/subaddress.dart'; part 'monero_subaddress_list.g.dart'; -class MoneroSubaddressList = MoneroSubaddressListBase - with _$MoneroSubaddressList; +class MoneroSubaddressList = MoneroSubaddressListBase with _$MoneroSubaddressList; abstract class MoneroSubaddressListBase with Store { MoneroSubaddressListBase() - : _isRefreshing = false, - _isUpdating = false, - subaddresses = ObservableList(); + : _isRefreshing = false, + _isUpdating = false, + subaddresses = ObservableList(); + + final List _usedAddresses = []; @observable ObservableList subaddresses; @@ -49,20 +50,24 @@ abstract class MoneroSubaddressListBase with Store { subaddresses = [primary] + rest.toList(); } - return subaddresses - .map((subaddressRow) => Subaddress( + return subaddresses.map((subaddressRow) { + final hasDefaultAddressName = + subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() || + subaddressRow.getLabel().toLowerCase() == 'Untitled account'.toLowerCase(); + final isPrimaryAddress = subaddressRow.getId() == 0 && hasDefaultAddressName; + return Subaddress( id: subaddressRow.getId(), address: subaddressRow.getAddress(), - label: subaddressRow.getId() == 0 && - subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() - ? 'Primary address' - : subaddressRow.getLabel())) - .toList(); + label: isPrimaryAddress + ? 'Primary address' + : hasDefaultAddressName + ? '' + : subaddressRow.getLabel()); + }).toList(); } Future addSubaddress({required int accountIndex, required String label}) async { - await subaddress_list.addSubaddress( - accountIndex: accountIndex, label: label); + await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label); update(accountIndex: accountIndex); } @@ -88,4 +93,59 @@ abstract class MoneroSubaddressListBase with Store { rethrow; } } + + Future updateWithAutoGenerate({ + required int accountIndex, + required String defaultLabel, + required List usedAddresses, + }) async { + _usedAddresses.addAll(usedAddresses); + if (_isUpdating) { + return; + } + + try { + _isUpdating = true; + refresh(accountIndex: accountIndex); + subaddresses.clear(); + final newSubAddresses = + await _getAllUnusedAddresses(accountIndex: accountIndex, label: defaultLabel); + subaddresses.addAll(newSubAddresses); + } catch (e) { + rethrow; + } finally { + _isUpdating = false; + } + } + + Future> _getAllUnusedAddresses( + {required int accountIndex, required String label}) async { + final allAddresses = subaddress_list.getAllSubaddresses(); + + if (allAddresses.isEmpty || _usedAddresses.contains(allAddresses.last.getAddress())) { + final isAddressUnused = await _newSubaddress(accountIndex: accountIndex, label: label); + if (!isAddressUnused) { + return await _getAllUnusedAddresses(accountIndex: accountIndex, label: label); + } + } + + return allAddresses + .map((subaddressRow) => Subaddress( + id: subaddressRow.getId(), + address: subaddressRow.getAddress(), + label: subaddressRow.getId() == 0 && + subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() + ? 'Primary address' + : subaddressRow.getLabel())) + .toList(); + } + + Future _newSubaddress({required int accountIndex, required String label}) async { + await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label); + + return subaddress_list + .getAllSubaddresses() + .where((subaddressRow) => !_usedAddresses.contains(subaddressRow.getAddress())) + .isNotEmpty; + } } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 12381af44..405b2cc54 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -51,12 +51,14 @@ abstract class MoneroWalletBase extends WalletBase walletAddresses.account, (Account? account) { if (account == null) { return; @@ -67,7 +69,11 @@ abstract class MoneroWalletBase extends WalletBase isEnabledAutoGenerateSubaddress, (bool enabled) { + _updateSubAddress(enabled, account: walletAddresses.account); }); } @@ -76,7 +82,11 @@ abstract class MoneroWalletBase extends WalletBase unspentCoinsInfo; @override - MoneroWalletAddresses walletAddresses; + late MoneroWalletAddresses walletAddresses; + + @override + @observable + bool isEnabledAutoGenerateSubaddress; @override @observable @@ -294,6 +304,14 @@ abstract class MoneroWalletBase extends WalletBase save() async { + await walletAddresses.updateUsedSubaddress(); + + if (isEnabledAutoGenerateSubaddress) { + walletAddresses.updateUnusedSubaddress( + accountIndex: walletAddresses.account?.id ?? 0, + defaultLabel: walletAddresses.account?.label ?? ''); + } + await walletAddresses.updateAddressesInBox(); await backupWalletFiles(name); await monero_wallet.store(); @@ -386,7 +404,7 @@ abstract class MoneroWalletBase extends WalletBase updateUnspent() async { - // refreshCoins(walletAddresses.account!.id); + refreshCoins(walletAddresses.account!.id); unspentCoins.clear(); @@ -618,4 +636,15 @@ abstract class MoneroWalletBase extends WalletBase updateUsedSubaddress() async { + final transactions = _moneroTransactionHistory.transactions.values.toList(); + + transactions.forEach((element) { + final accountIndex = element.accountIndex; + final addressIndex = element.addressIndex; + usedAddresses.add(getAddress(accountIndex: accountIndex, addressIndex: addressIndex)); + }); + } + + Future updateUnusedSubaddress( + {required int accountIndex, required String defaultLabel}) async { + await subaddressList.updateWithAutoGenerate( + accountIndex: accountIndex, + defaultLabel: defaultLabel, + usedAddresses: usedAddresses.toList()); + subaddress = subaddressList.subaddresses.last; + address = subaddress!.address; + } +} diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 181bc7c66..3675191c0 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -57,7 +57,7 @@ class MoneroWalletService extends WalletService< final Box walletInfoSource; final Box unspentCoinsInfoSource; - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -128,13 +128,20 @@ class MoneroWalletService extends WalletService< } catch (e) { // TODO: Implement Exception for wallet list service. - if ((e.toString().contains('bad_alloc') || + final bool isBadAlloc = e.toString().contains('bad_alloc') || (e is WalletOpeningException && - (e.message == 'std::bad_alloc' || - e.message.contains('bad_alloc')))) || - (e.toString().contains('does not correspond') || - (e is WalletOpeningException && - e.message.contains('does not correspond')))) { + (e.message == 'std::bad_alloc' || e.message.contains('bad_alloc'))); + + final bool doesNotCorrespond = e.toString().contains('does not correspond') || + (e is WalletOpeningException && e.message.contains('does not correspond')); + + final bool isMissingCacheFilesIOS = e.toString().contains('basic_string') || + (e is WalletOpeningException && e.message.contains('basic_string')); + + final bool isMissingCacheFilesAndroid = e.toString().contains('input_stream') || + (e is WalletOpeningException && e.message.contains('input_stream')); + + if (isBadAlloc || doesNotCorrespond || isMissingCacheFilesIOS || isMissingCacheFilesAndroid) { await restoreOrResetWalletFiles(name); return openWallet(name, password); } diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index e1cbb5b59..7185bf581 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -3,8 +3,10 @@ #include #include #include +#include #include #include +#include #include "thread" #include "CwWalletListener.h" #if __APPLE__ @@ -135,7 +137,7 @@ extern "C" int8_t direction; int8_t isPending; uint32_t subaddrIndex; - + char *hash; char *paymentId; @@ -151,7 +153,7 @@ extern "C" std::set::iterator it = subIndex.begin(); subaddrIndex = *it; confirmations = transaction->confirmations(); - datetime = static_cast(transaction->timestamp()); + datetime = static_cast(transaction->timestamp()); direction = transaction->direction(); isPending = static_cast(transaction->isPending()); std::string *hash_str = new std::string(transaction->hash()); @@ -180,6 +182,62 @@ extern "C" } }; + struct CoinsInfoRow + { + uint64_t blockHeight; + char *hash; + uint64_t internalOutputIndex; + uint64_t globalOutputIndex; + bool spent; + bool frozen; + uint64_t spentHeight; + uint64_t amount; + bool rct; + bool keyImageKnown; + uint64_t pkIndex; + uint32_t subaddrIndex; + uint32_t subaddrAccount; + char *address; + char *addressLabel; + char *keyImage; + uint64_t unlockTime; + bool unlocked; + char *pubKey; + bool coinbase; + char *description; + + CoinsInfoRow(Monero::CoinsInfo *coinsInfo) + { + blockHeight = coinsInfo->blockHeight(); + std::string *hash_str = new std::string(coinsInfo->hash()); + hash = strdup(hash_str->c_str()); + internalOutputIndex = coinsInfo->internalOutputIndex(); + globalOutputIndex = coinsInfo->globalOutputIndex(); + spent = coinsInfo->spent(); + frozen = coinsInfo->frozen(); + spentHeight = coinsInfo->spentHeight(); + amount = coinsInfo->amount(); + rct = coinsInfo->rct(); + keyImageKnown = coinsInfo->keyImageKnown(); + pkIndex = coinsInfo->pkIndex(); + subaddrIndex = coinsInfo->subaddrIndex(); + subaddrAccount = coinsInfo->subaddrAccount(); + address = strdup(coinsInfo->address().c_str()) ; + addressLabel = strdup(coinsInfo->addressLabel().c_str()); + keyImage = strdup(coinsInfo->keyImage().c_str()); + unlockTime = coinsInfo->unlockTime(); + unlocked = coinsInfo->unlocked(); + pubKey = strdup(coinsInfo->pubKey().c_str()); + coinbase = coinsInfo->coinbase(); + description = strdup(coinsInfo->description().c_str()); + } + + void setUnlocked(bool unlocked); + + }; + + Monero::Coins *m_coins; + Monero::Wallet *m_wallet; Monero::TransactionHistory *m_transaction_history; MoneroWalletListener *m_listener; @@ -187,6 +245,7 @@ extern "C" Monero::SubaddressAccount *m_account; uint64_t m_last_known_wallet_height; uint64_t m_cached_syncing_blockchain_height = 0; + std::list m_coins_info; std::mutex store_lock; bool is_storing = false; @@ -194,7 +253,7 @@ extern "C" { m_wallet = wallet; m_listener = nullptr; - + if (wallet != nullptr) { @@ -222,6 +281,17 @@ extern "C" { m_subaddress = nullptr; } + + m_coins_info = std::list(); + + if (wallet != nullptr) + { + m_coins = wallet->coins(); + } + else + { + m_coins = nullptr; + } } Monero::Wallet *get_current_wallet() @@ -404,13 +474,14 @@ extern "C" return is_connected; } - bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error) + bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *socksProxyAddress, char *error) { nice(19); Monero::Wallet *wallet = get_current_wallet(); - + std::string _login = ""; std::string _password = ""; + std::string _socksProxyAddress = ""; if (login != nullptr) { @@ -422,7 +493,12 @@ extern "C" _password = std::string(password); } - bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet); + if (socksProxyAddress != nullptr) + { + _socksProxyAddress = std::string(socksProxyAddress); + } + + bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet, _socksProxyAddress); if (!inited) { @@ -479,10 +555,19 @@ extern "C" } bool transaction_create(char *address, char *payment_id, char *amount, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) + uint8_t priority_raw, uint32_t subaddr_account, + char **preferred_inputs, uint32_t preferred_inputs_size, + Utf8Box &error, PendingTransactionRaw &pendingTransaction) { nice(19); - + + std::set _preferred_inputs; + + for (int i = 0; i < preferred_inputs_size; i++) { + _preferred_inputs.insert(std::string(*preferred_inputs)); + preferred_inputs++; + } + auto priority = static_cast(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -495,13 +580,13 @@ extern "C" if (amount != nullptr) { uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount)); - transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account); + transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } else { - transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional(), m_wallet->defaultMixin(), priority, subaddr_account); + transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs); } - + int status = transaction->status(); if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical) @@ -519,7 +604,9 @@ extern "C" } bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) + uint8_t priority_raw, uint32_t subaddr_account, + char **preferred_inputs, uint32_t preferred_inputs_size, + Utf8Box &error, PendingTransactionRaw &pendingTransaction) { nice(19); @@ -533,6 +620,13 @@ extern "C" amounts++; } + std::set _preferred_inputs; + + for (int i = 0; i < preferred_inputs_size; i++) { + _preferred_inputs.insert(std::string(*preferred_inputs)); + preferred_inputs++; + } + auto priority = static_cast(priority_raw); std::string _payment_id; Monero::PendingTransaction *transaction; @@ -792,6 +886,91 @@ extern "C" return m_wallet->trustedDaemon(); } + CoinsInfoRow* coin(int index) + { + if (index >= 0 && index < m_coins_info.size()) { + std::list::iterator it = m_coins_info.begin(); + std::advance(it, index); + Monero::CoinsInfo* element = *it; + std::cout << "Element at index " << index << ": " << element << std::endl; + return new CoinsInfoRow(element); + } else { + std::cout << "Invalid index." << std::endl; + return nullptr; // Return a default value (nullptr) for invalid index + } + } + + void refresh_coins(uint32_t accountIndex) + { + m_coins_info.clear(); + + m_coins->refresh(); + for (const auto i : m_coins->getAll()) { + if (i->subaddrAccount() == accountIndex && !(i->spent())) { + m_coins_info.push_back(i); + } + } + } + + uint64_t coins_count() + { + return m_coins_info.size(); + } + + CoinsInfoRow** coins_from_account(uint32_t accountIndex) + { + std::vector matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinInfo = coin(i); + if (coinInfo->subaddrAccount == accountIndex) { + matchingCoins.push_back(coinInfo); + } + } + + CoinsInfoRow** result = new CoinsInfoRow*[matchingCoins.size()]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + CoinsInfoRow** coins_from_txid(const char* txid, size_t* count) + { + std::vector matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinInfo = coin(i); + if (std::string(coinInfo->hash) == txid) { + matchingCoins.push_back(coinInfo); + } + } + + *count = matchingCoins.size(); + CoinsInfoRow** result = new CoinsInfoRow*[*count]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + CoinsInfoRow** coins_from_key_image(const char** keyimages, size_t keyimageCount, size_t* count) + { + std::vector matchingCoins; + + for (int i = 0; i < coins_count(); i++) { + CoinsInfoRow* coinsInfoRow = coin(i); + for (size_t j = 0; j < keyimageCount; j++) { + if (coinsInfoRow->keyImageKnown && std::string(coinsInfoRow->keyImage) == keyimages[j]) { + matchingCoins.push_back(coinsInfoRow); + break; + } + } + } + + *count = matchingCoins.size(); + CoinsInfoRow** result = new CoinsInfoRow*[*count]; + std::copy(matchingCoins.begin(), matchingCoins.end(), result); + return result; + } + + #ifdef __cplusplus } #endif diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 437184a7d..37e08e7ca 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -286,10 +286,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -310,10 +310,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -326,10 +326,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -350,10 +350,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -366,10 +366,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -406,10 +406,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -603,10 +603,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -672,5 +672,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6f441c587..2f51f68f7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -8,25 +8,6 @@ PODS: - Flutter - ReachabilitySwift - CryptoSwift (1.7.1) - - cw_haven (0.0.1): - - cw_haven/Boost (= 0.0.1) - - cw_haven/Haven (= 0.0.1) - - cw_haven/OpenSSL (= 0.0.1) - - cw_haven/Sodium (= 0.0.1) - - cw_shared_external - - Flutter - - cw_haven/Boost (0.0.1): - - cw_shared_external - - Flutter - - cw_haven/Haven (0.0.1): - - cw_shared_external - - Flutter - - cw_haven/OpenSSL (0.0.1): - - cw_shared_external - - Flutter - - cw_haven/Sodium (0.0.1): - - cw_shared_external - - Flutter - cw_monero (0.0.2): - cw_monero/Boost (= 0.0.2) - cw_monero/Monero (= 0.0.2) @@ -159,7 +140,6 @@ DEPENDENCIES: - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - CryptoSwift - - cw_haven (from `.symlinks/plugins/cw_haven/ios`) - cw_monero (from `.symlinks/plugins/cw_monero/ios`) - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) @@ -205,8 +185,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/barcode_scan2/ios" connectivity_plus: :path: ".symlinks/plugins/connectivity_plus/ios" - cw_haven: - :path: ".symlinks/plugins/cw_haven/ios" cw_monero: :path: ".symlinks/plugins/cw_monero/ios" cw_shared_external: @@ -261,7 +239,6 @@ SPEC CHECKSUMS: BigInt: f668a80089607f521586bbe29513d708491ef2f7 connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e CryptoSwift: d3d18dc357932f7e6d580689e065cf1f176007c1 - cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 424adbfec..2813ec6c3 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -232,6 +232,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 03581f156..6e7bd67da 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -246,6 +246,7 @@ class BackupService { final useEtherscan = data[PreferencesKey.useEtherscan] as bool?; final syncAll = data[PreferencesKey.syncAllKey] as bool?; final syncMode = data[PreferencesKey.syncModeKey] as int?; + final autoGenerateSubaddressStatus = data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; await _sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName); @@ -296,6 +297,9 @@ class BackupService { if (fiatApiMode != null) await _sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, fiatApiMode); + if (autoGenerateSubaddressStatus != null) + await _sharedPreferences.setInt(PreferencesKey.autoGenerateSubaddressStatusKey, + autoGenerateSubaddressStatus); if (currentPinLength != null) await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength); @@ -523,6 +527,8 @@ class BackupService { _sharedPreferences.getInt(PreferencesKey.syncModeKey), PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey), + PreferencesKey.autoGenerateSubaddressStatusKey: + _sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey), }; return json.encode(preferences); diff --git a/lib/core/fiat_conversion_service.dart b/lib/core/fiat_conversion_service.dart index 9690c430a..479aa3b82 100644 --- a/lib/core/fiat_conversion_service.dart +++ b/lib/core/fiat_conversion_service.dart @@ -21,7 +21,7 @@ Future _fetchPrice(Map args) async { 'key': secrets.fiatApiKey, }; - double price = 0.0; + num price = 0.0; try { late final Uri uri; @@ -41,12 +41,12 @@ Future _fetchPrice(Map args) async { final results = responseJSON['results'] as Map; if (results.isNotEmpty) { - price = results.values.first as double; + price = results.values.first as num; } - return price; + return price.toDouble(); } catch (e) { - return price; + return price.toDouble(); } } diff --git a/lib/di.dart b/lib/di.dart index db7eece6c..f70854c6d 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; @@ -250,7 +251,6 @@ Future setup({ if (!_isSetupFinished) { getIt.registerSingletonAsync(() => SharedPreferences.getInstance()); } - if (!_isSetupFinished) { getIt.registerFactory(() => BackgroundTasks()); } diff --git a/lib/entities/auto_generate_subaddress_status.dart b/lib/entities/auto_generate_subaddress_status.dart new file mode 100644 index 000000000..6d6cc406c --- /dev/null +++ b/lib/entities/auto_generate_subaddress_status.dart @@ -0,0 +1,13 @@ + +enum AutoGenerateSubaddressStatus { + initialized(1), + enabled(2), + disabled(3); + + const AutoGenerateSubaddressStatus(this.value); + final int value; + + static AutoGenerateSubaddressStatus deserialize({required int raw}) => + AutoGenerateSubaddressStatus.values.firstWhere((e) => e.value == raw); + +} \ No newline at end of file diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 42b6d5324..d8602dd63 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,4 +1,4 @@ -import 'dart:io' show File, Platform; +import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; @@ -6,7 +6,7 @@ import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:flutter/foundation.dart'; import 'package:cake_wallet/core/secure_storage.dart'; import 'package:hive/hive.dart'; -import 'package:share_plus/share_plus.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/wallet_type.dart'; @@ -28,7 +28,7 @@ const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; -Future defaultSettingsMigration( +Future defaultSettingsMigration( {required int version, required SharedPreferences sharedPreferences, required SecureStorage secureStorage, @@ -43,6 +43,8 @@ Future defaultSettingsMigration( // check current nodes for nullability regardless of the version await checkCurrentNodes(nodes, sharedPreferences); + await _validateWalletInfoBoxData(walletInfoSource); + final isNewInstall = sharedPreferences .getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null; @@ -179,6 +181,66 @@ Future defaultSettingsMigration( PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future _validateWalletInfoBoxData(Box walletInfoSource) async { + final root = await getApplicationDocumentsDirectory(); + + for (var type in WalletType.values) { + if (type == WalletType.none) { + continue; + } + + String prefix = walletTypeToString(type).toLowerCase(); + Directory walletsDir = Directory('${root.path}/wallets/$prefix/'); + + if (!walletsDir.existsSync()) { + continue; + } + + List walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList(); + + for (var name in walletNames) { + final dir = Directory(await pathForWalletDir(name: name, type: type)); + + final walletFiles = dir.listSync(); + final hasCacheFile = walletFiles.any((element) => element.path.contains("$name/$name")); + + if (!hasCacheFile) { + continue; + } + + if (type == WalletType.monero || type == WalletType.haven) { + final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys")); + + if (!hasKeysFile) { + continue; + } + } + + final id = prefix + '_' + name; + final exist = walletInfoSource.values.any((el) => el.id == id); + + if (exist) { + continue; + } + + final walletInfo = WalletInfo.external( + id: id, + type: type, + name: name, + isRecovery: true, + restoreHeight: 0, + date: DateTime.now(), + dirPath: dir.path, + path: '${dir.path}/$name', + address: '', + showIntroCakePayCard: false, + ); + + walletInfoSource.add(walletInfo); + } + } +} + Future validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async { if (bitcoin == null) { return; @@ -226,7 +288,7 @@ Future changeMoneroCurrentNodeToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final node = getMoneroDefaultNode(nodes: nodes); - final nodeId = node?.key as int ?? 0; // 0 - England + final nodeId = node.key as int? ?? 0; // 0 - England await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, nodeId); } @@ -279,7 +341,7 @@ Future changeBitcoinCurrentElectrumServerToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final server = getBitcoinDefaultElectrumServer(nodes: nodes); - final serverId = server?.key as int ?? 0; + final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId); } @@ -288,7 +350,7 @@ Future changeLitecoinCurrentElectrumServerToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final server = getLitecoinDefaultElectrumServer(nodes: nodes); - final serverId = server?.key as int ?? 0; + final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, serverId); } @@ -297,7 +359,7 @@ Future changeHavenCurrentNodeToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final node = getHavenDefaultNode(nodes: nodes); - final nodeId = node?.key as int ?? 0; + final nodeId = node?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, nodeId); } diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index c50629c1b..7b4d3d0dc 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -50,6 +50,7 @@ class PreferencesKey { '${PreferencesKey.moneroWalletPasswordUpdateV1Base}_${name}'; static const exchangeProvidersSelection = 'exchange-providers-selection'; + static const autoGenerateSubaddressStatusKey = 'auto_generate_subaddress_status'; static const clearnetDonationLink = 'clearnet_donation_link'; static const onionDonationLink = 'onion_donation_link'; static const lastSeenAppVersion = 'last_seen_app_version'; diff --git a/lib/main.dart b/lib/main.dart index 8ade81e3e..1ec18f738 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,9 @@ import 'package:cake_wallet/buy/order.dart'; 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:cw_core/address_info.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'; @@ -40,6 +42,7 @@ 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,7 +61,8 @@ Future main() async { return true; }; - await Hive.close(); + + await CakeHive.close(); await initializeAppConfigs(); @@ -71,69 +75,73 @@ Future main() async { Future initializeAppConfigs() async { setRootDirFromEnv(); final appDir = await getAppDir(); - Hive.init(appDir.path); + CakeHive.init(appDir.path); - if (!Hive.isAdapterRegistered(Contact.typeId)) { - Hive.registerAdapter(ContactAdapter()); + if (!CakeHive.isAdapterRegistered(Contact.typeId)) { + CakeHive.registerAdapter(ContactAdapter()); } - if (!Hive.isAdapterRegistered(Node.typeId)) { - Hive.registerAdapter(NodeAdapter()); + if (!CakeHive.isAdapterRegistered(Node.typeId)) { + CakeHive.registerAdapter(NodeAdapter()); } - if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) { - Hive.registerAdapter(TransactionDescriptionAdapter()); + if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) { + CakeHive.registerAdapter(TransactionDescriptionAdapter()); } - if (!Hive.isAdapterRegistered(Trade.typeId)) { - Hive.registerAdapter(TradeAdapter()); + if (!CakeHive.isAdapterRegistered(Trade.typeId)) { + CakeHive.registerAdapter(TradeAdapter()); } - if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { - Hive.registerAdapter(WalletInfoAdapter()); + if (!CakeHive.isAdapterRegistered(AddressInfo.typeId)) { + CakeHive.registerAdapter(AddressInfoAdapter()); } - if (!Hive.isAdapterRegistered(walletTypeTypeId)) { - Hive.registerAdapter(WalletTypeAdapter()); + if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { + CakeHive.registerAdapter(WalletInfoAdapter()); } - if (!Hive.isAdapterRegistered(Template.typeId)) { - Hive.registerAdapter(TemplateAdapter()); + if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { + CakeHive.registerAdapter(WalletTypeAdapter()); } - if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) { - Hive.registerAdapter(ExchangeTemplateAdapter()); + if (!CakeHive.isAdapterRegistered(Template.typeId)) { + CakeHive.registerAdapter(TemplateAdapter()); } - if (!Hive.isAdapterRegistered(Order.typeId)) { - Hive.registerAdapter(OrderAdapter()); + if (!CakeHive.isAdapterRegistered(ExchangeTemplate.typeId)) { + CakeHive.registerAdapter(ExchangeTemplateAdapter()); } - if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { - Hive.registerAdapter(UnspentCoinsInfoAdapter()); + if (!CakeHive.isAdapterRegistered(Order.typeId)) { + CakeHive.registerAdapter(OrderAdapter()); } - if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { - Hive.registerAdapter(AnonpayInvoiceInfoAdapter()); + if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { + CakeHive.registerAdapter(UnspentCoinsInfoAdapter()); } - final secureStorage = secureStorageShared; - 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 Hive.openBox(Contact.boxName); - final nodes = await Hive.openBox(Node.boxName); - final transactionDescriptions = await Hive.openBox( - TransactionDescription.boxName, - encryptionKey: transactionDescriptionsBoxKey); - final trades = await Hive.openBox(Trade.boxName, encryptionKey: tradesBoxKey); - final orders = await Hive.openBox(Order.boxName, encryptionKey: ordersBoxKey); - final walletInfoSource = await Hive.openBox(WalletInfo.boxName); - final templates = await Hive.openBox