diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index e2b932202..47378eef5 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -127,6 +127,7 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart + echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties diff --git a/assets/images/live_support.png b/assets/images/live_support.png new file mode 100644 index 000000000..89ad61f45 Binary files /dev/null and b/assets/images/live_support.png differ diff --git a/assets/images/more_links.png b/assets/images/more_links.png new file mode 100644 index 000000000..97891f3ad Binary files /dev/null and b/assets/images/more_links.png differ diff --git a/assets/images/wallet_guides.png b/assets/images/wallet_guides.png new file mode 100644 index 000000000..3f2d9f270 Binary files /dev/null and b/assets/images/wallet_guides.png differ 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..0961182bc --- /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 ERC20_TOKEN_TYPE_ID = 12; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 3fa45b44c..59a1450f6 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -3,6 +3,7 @@ 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; @@ -37,7 +38,7 @@ class Node extends HiveObject with Keyable { trusted = map['trusted'] as bool? ?? false, socksProxyAddress = map['socksProxyPort'] as String?; - static const typeId = 1; + static const typeId = NODE_TYPE_ID; static const boxName = 'Nodes'; @HiveField(0, defaultValue: '') diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 75c13f2cd..33be2eb2c 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'unspent_coins_info.g.dart'; @@ -14,7 +15,7 @@ class UnspentCoinsInfo extends HiveObject { required this.vout, required this.value}); - static const typeId = 9; + static const typeId = UNSPENT_COINS_INFO_TYPE_ID; static const boxName = 'Unspent'; static const boxKey = 'unspentBoxKey'; @@ -45,4 +46,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_info.dart b/cw_core/lib/wallet_info.dart index a25702cf7..6b3fa9e98 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,7 +1,7 @@ -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_core/wallet_type.dart'; import 'dart:async'; +import 'package:cw_core/hive_type_ids.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:hive/hive.dart'; part 'wallet_info.g.dart'; @@ -30,7 +30,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: '') diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index a65839041..62c2ad410 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.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 'wallet_type.g.dart'; @@ -10,9 +11,8 @@ const walletTypes = [ WalletType.haven, WalletType.ethereum, ]; -const walletTypeTypeId = 5; -@HiveType(typeId: walletTypeTypeId) +@HiveType(typeId: WALLET_TYPE_TYPE_ID) enum WalletType { @HiveField(0) monero, diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index ae05e6a4f..967a116e6 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'; @@ -58,8 +59,8 @@ abstract class EthereumWalletBase this.walletInfo = walletInfo; transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password); - if (!Hive.isAdapterRegistered(Erc20Token.typeId)) { - Hive.registerAdapter(Erc20TokenAdapter()); + if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { + CakeHive.registerAdapter(Erc20TokenAdapter()); } _sharedPrefs.complete(SharedPreferences.getInstance()); @@ -95,7 +96,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(); _privateKey = await getPrivateKey(_mnemonic, _password); diff --git a/lib/anonpay/anonpay_invoice_info.dart b/lib/anonpay/anonpay_invoice_info.dart index 89613224e..bd6776d00 100644 --- a/lib/anonpay/anonpay_invoice_info.dart +++ b/lib/anonpay/anonpay_invoice_info.dart @@ -1,4 +1,5 @@ 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'; @@ -35,7 +36,7 @@ class AnonpayInvoiceInfo extends HiveObject with Keyable implements AnonpayInfoB @HiveField(13) final String provider; - static const typeId = 10; + static const typeId = ANONPAY_INVOICE_INFO_TYPE_ID; static const boxName = 'AnonpayInvoiceInfo'; AnonpayInvoiceInfo({ diff --git a/lib/buy/order.dart b/lib/buy/order.dart index 387fbcd34..5a677d291 100644 --- a/lib/buy/order.dart +++ b/lib/buy/order.dart @@ -1,7 +1,8 @@ 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'; @@ -26,7 +27,7 @@ class Order extends HiveObject { } } - static const typeId = 8; + static const typeId = ORDER_TYPE_ID; static const boxName = 'Orders'; static const boxKey = 'ordersBoxKey'; @@ -66,4 +67,4 @@ class Order extends HiveObject { BuyProviderDescription.deserialize(raw: providerRaw); String amountFormatted() => formatAmount(amount); -} \ No newline at end of file +} diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 2e27d83c9..6476891ed 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -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'; @@ -10,6 +9,7 @@ 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,6 +17,7 @@ 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 { @@ -170,14 +171,14 @@ class BackupService { Future> _reloadHiveWalletInfoBox() async { final appDir = await getApplicationDocumentsDirectory(); - await Hive.close(); - Hive.init(appDir.path); + await CakeHive.close(); + CakeHive.init(appDir.path); - if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { - Hive.registerAdapter(WalletInfoAdapter()); + if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) { + CakeHive.registerAdapter(WalletInfoAdapter()); } - return await Hive.openBox(WalletInfo.boxName); + return await CakeHive.openBox(WalletInfo.boxName); } Future _importPreferencesDump() async { diff --git a/lib/di.dart b/lib/di.dart index b02742e64..2a54c85a3 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -36,6 +36,8 @@ 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'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; +import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; +import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; @@ -869,6 +871,12 @@ Future setup({ getIt.registerFactory(() => SupportPage(getIt.get())); + getIt.registerFactory(() => + SupportChatPage( + getIt.get(), secureStorage: getIt.get())); + + getIt.registerFactory(() => SupportOtherLinksPage(getIt.get())); + getIt.registerFactory(() { final wallet = getIt.get().wallet; diff --git a/lib/entities/contact.dart b/lib/entities/contact.dart index e111429ca..cd4fa55a2 100644 --- a/lib/entities/contact.dart +++ b/lib/entities/contact.dart @@ -1,8 +1,7 @@ -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/hive_type_ids.dart'; import 'package:cw_core/keyable.dart'; +import 'package:hive/hive.dart'; part 'contact.g.dart'; @@ -14,7 +13,7 @@ class Contact extends HiveObject with Keyable { } } - static const typeId = 0; + static const typeId = CONTACT_TYPE_ID; static const boxName = 'Contacts'; @HiveField(0, defaultValue: '') diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index 5fc4983d7..e67380bb8 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,23 +1,18 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:hive/hive.dart'; +import 'package:cw_core/cake_hive.dart'; Future> getEncryptionKey( {required String forKey, required FlutterSecureStorage secureStorage}) async { - final stringifiedKey = - await secureStorage.read(key: 'transactionDescriptionsBoxKey'); + final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey'); List key; if (stringifiedKey == null) { - key = Hive.generateSecureKey(); + key = CakeHive.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/template.dart b/lib/entities/template.dart index 6955136e0..7cdd2c74a 100644 --- a/lib/entities/template.dart +++ b/lib/entities/template.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'template.g.dart'; @@ -14,7 +15,7 @@ class Template extends HiveObject { required this.amountFiatRaw, this.additionalRecipientsRaw}); - static const typeId = 6; + static const typeId = TEMPLATE_TYPE_ID; static const boxName = 'Template'; @HiveField(0) diff --git a/lib/entities/transaction_description.dart b/lib/entities/transaction_description.dart index 86d6b043a..088f9c480 100644 --- a/lib/entities/transaction_description.dart +++ b/lib/entities/transaction_description.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'transaction_description.g.dart'; @@ -6,7 +7,7 @@ part 'transaction_description.g.dart'; class TransactionDescription extends HiveObject { TransactionDescription({required this.id, this.recipientAddress, this.transactionNote}); - static const typeId = 2; + static const typeId = TRANSACTION_TYPE_ID; static const boxName = 'TransactionDescriptions'; static const boxKey = 'transactionDescriptionsBoxKey'; diff --git a/lib/exchange/exchange_template.dart b/lib/exchange/exchange_template.dart index dcfd8d8e8..2182efd8c 100644 --- a/lib/exchange/exchange_template.dart +++ b/lib/exchange/exchange_template.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; part 'exchange_template.g.dart'; @@ -14,7 +15,7 @@ class ExchangeTemplate extends HiveObject { required this.depositCurrencyTitleRaw, required this.receiveCurrencyTitleRaw}); - static const typeId = 7; + static const typeId = EXCHANGE_TEMPLATE_TYPE_ID; static const boxName = 'ExchangeTemplate'; @HiveField(0) diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index 70dfa5713..db8c8fb3b 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -1,8 +1,9 @@ -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'; @@ -41,7 +42,7 @@ class Trade extends HiveObject { } } - static const typeId = 3; + static const typeId = TRADE_TYPE_ID; static const boxName = 'Trades'; static const boxKey = 'tradesBoxKey'; diff --git a/lib/main.dart b/lib/main.dart index e0cf58e62..62a0bfc9c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ 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:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -38,6 +39,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(); @@ -57,7 +59,7 @@ Future main() async { return true; }; - await Hive.close(); + await CakeHive.close(); await initializeAppConfigs(); @@ -69,50 +71,50 @@ Future main() async { Future initializeAppConfigs() async { final appDir = await getApplicationDocumentsDirectory(); - 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(WalletInfo.typeId)) { + CakeHive.registerAdapter(WalletInfoAdapter()); } - if (!Hive.isAdapterRegistered(walletTypeTypeId)) { - Hive.registerAdapter(WalletTypeAdapter()); + if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { + CakeHive.registerAdapter(WalletTypeAdapter()); } - if (!Hive.isAdapterRegistered(Template.typeId)) { - Hive.registerAdapter(TemplateAdapter()); + if (!CakeHive.isAdapterRegistered(Template.typeId)) { + CakeHive.registerAdapter(TemplateAdapter()); } - if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) { - Hive.registerAdapter(ExchangeTemplateAdapter()); + if (!CakeHive.isAdapterRegistered(ExchangeTemplate.typeId)) { + CakeHive.registerAdapter(ExchangeTemplateAdapter()); } - if (!Hive.isAdapterRegistered(Order.typeId)) { - Hive.registerAdapter(OrderAdapter()); + if (!CakeHive.isAdapterRegistered(Order.typeId)) { + CakeHive.registerAdapter(OrderAdapter()); } - if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { - Hive.registerAdapter(UnspentCoinsInfoAdapter()); + if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { + CakeHive.registerAdapter(UnspentCoinsInfoAdapter()); } - if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { - Hive.registerAdapter(AnonpayInvoiceInfoAdapter()); + if (!CakeHive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) { + CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); } final secureStorage = FlutterSecureStorage(); @@ -120,21 +122,21 @@ Future initializeAppConfigs() async { 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( + 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 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