diff --git a/.gitignore b/.gitignore index 9300421f4..6deb196ac 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,7 @@ cw_monero/cw_monero/android/.cxx/ **/*.g.dart android/key.properties +android/app/key.jks **/tool/.secrets-prod.json **/tool/.secrets-test.json diff --git a/assets/images/digibyte.png b/assets/images/digibyte.png new file mode 100644 index 000000000..0045c6852 Binary files /dev/null and b/assets/images/digibyte.png differ diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 2b8c489d2..38e769d15 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; -import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; +import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 3d7462fa1..ee3b0e628 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; -import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; +import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet.dart'; import 'package:cw_core/wallet_service.dart'; @@ -101,7 +101,7 @@ class LitecoinWalletService extends WalletService< Future restoreFromSeed( BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { - throw BitcoinMnemonicIsIncorrectException(); + throw LitecoinMnemonicIsIncorrectException(); } final wallet = await LitecoinWalletBase.create( diff --git a/cw_bitcoin/lib/bitcoin_mnemonic_is_incorrect_exception.dart b/cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart similarity index 50% rename from cw_bitcoin/lib/bitcoin_mnemonic_is_incorrect_exception.dart rename to cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart index 8d0583ce5..779bd3ea2 100644 --- a/cw_bitcoin/lib/bitcoin_mnemonic_is_incorrect_exception.dart +++ b/cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart @@ -3,3 +3,9 @@ class BitcoinMnemonicIsIncorrectException implements Exception { String toString() => 'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; } + +class LitecoinMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Litecoin mnemonic has incorrect format. Mnemonic should contain 24 words separated by space.'; +} diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 62c0ad437..67581ecb8 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -9,7 +9,8 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen required this.decimals, this.fullName, this.iconPath, - this.tag, this.enabled = false, + this.tag, + this.enabled = false, }) : super(title: title, raw: raw); @@ -100,6 +101,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.usdtPoly, CryptoCurrency.usdcEPoly, CryptoCurrency.kaspa, + CryptoCurrency.digibyte, ]; static const havenCurrencies = [ @@ -211,8 +213,9 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29); static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); - static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kaspa', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); - static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); + static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); + static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8); + static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static final Map _rawCurrencyMap = diff --git a/cw_evm/lib/evm_chain_wallet_addresses.dart b/cw_evm/lib/evm_chain_wallet_addresses.dart index d5d39f21d..4615d79ed 100644 --- a/cw_evm/lib/evm_chain_wallet_addresses.dart +++ b/cw_evm/lib/evm_chain_wallet_addresses.dart @@ -14,6 +14,7 @@ abstract class EVMChainWalletAddressesBase extends WalletAddresses with Store { super(walletInfo); @override + @observable String address; @override diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 1a34e4bd6..ab4bfb0b0 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -576,15 +576,19 @@ abstract class MoneroWalletBase return; } - final height = _getHeightByDate(walletInfo.date); - - if (height > MIN_RESTORE_HEIGHT) { - monero_wallet.setRecoveringFromSeed(isRecovery: true); - monero_wallet.setRefreshFromBlockHeight(height: height); - return; + int height = 0; + try { + height = _getHeightByDate(walletInfo.date); + } catch (e, s) { + onError?.call(FlutterErrorDetails( + exception: e, + stack: s, + library: this.runtimeType.toString(), + )); } - throw Exception("height isn't > $MIN_RESTORE_HEIGHT!"); + monero_wallet.setRecoveringFromSeed(isRecovery: true); + monero_wallet.setRefreshFromBlockHeight(height: height); } int _getHeightDistance(DateTime date) { @@ -600,7 +604,7 @@ abstract class MoneroWalletBase final heightDistance = _getHeightDistance(date); if (nodeHeight <= 0) { - // the node returned 0 (an error state), so lets just restore from cache: + // the node returned 0 (an error state) throw Exception("nodeHeight is <= 0!"); } diff --git a/cw_solana/lib/default_spl_tokens.dart b/cw_solana/lib/default_spl_tokens.dart index f96d62d86..7acad78e0 100644 --- a/cw_solana/lib/default_spl_tokens.dart +++ b/cw_solana/lib/default_spl_tokens.dart @@ -25,7 +25,6 @@ class DefaultSPLTokens { mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', decimal: 6, mint: 'soEth', - enabled: true, iconPath: 'assets/images/eth_icon.png', ), SPLToken( @@ -34,7 +33,6 @@ class DefaultSPLTokens { mintAddress: 'So11111111111111111111111111111111111111112', decimal: 9, mint: 'WSOL', - enabled: true, iconPath: 'assets/images/sol_icon.png', ), SPLToken( diff --git a/lib/bitcoin_cash/cw_bitcoin_cash.dart b/lib/bitcoin_cash/cw_bitcoin_cash.dart index 7dbb8614f..6e169209f 100644 --- a/lib/bitcoin_cash/cw_bitcoin_cash.dart +++ b/lib/bitcoin_cash/cw_bitcoin_cash.dart @@ -1,12 +1,6 @@ part of 'bitcoin_cash.dart'; class CWBitcoinCash extends BitcoinCash { - @override - String getMnemonic(int? strength) => Mnemonic.generate(); - - @override - Uint8List getSeedFromMnemonic(String seed) => Mnemonic.toSeed(seed); - @override String getCashAddrFormat(String address) => AddressUtils.getCashAddrFormat(address); diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 432471655..853762a1c 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -257,9 +257,9 @@ class AddressValidator extends TextValidator { case CryptoCurrency.near: return [64]; case CryptoCurrency.btcln: - return null; + case CryptoCurrency.kaspa: default: - return []; + return null; } } diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index 2f83cef10..9bdee457c 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -67,7 +67,7 @@ class ProvidersHelper { case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.polygon: - return [ProviderType.askEachTime, ProviderType.dfx]; + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; case WalletType.solana: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.none: @@ -91,7 +91,7 @@ class ProvidersHelper { case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; case WalletType.polygon: - return [ProviderType.askEachTime, ProviderType.dfx]; + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; case WalletType.solana: return [ ProviderType.askEachTime, diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 5870b1c4d..a3b7eaf85 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/template.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; import 'package:cake_wallet/src/widgets/add_template_button.dart'; @@ -420,7 +421,9 @@ class SendPage extends BasePage { amount: S.of(_dialogContext).send_amount, amountValue: sendViewModel.pendingTransaction!.amountFormatted, fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, - fee: S.of(_dialogContext).send_fee, + fee: isEVMCompatibleChain(sendViewModel.walletType) + ? S.of(_dialogContext).send_estimated_fee + : S.of(_dialogContext).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, diff --git a/lib/src/widgets/scollable_with_bottom_section.dart b/lib/src/widgets/scollable_with_bottom_section.dart index 53f56716c..2487e6130 100644 --- a/lib/src/widgets/scollable_with_bottom_section.dart +++ b/lib/src/widgets/scollable_with_bottom_section.dart @@ -14,37 +14,28 @@ class ScrollableWithBottomSection extends StatefulWidget { final EdgeInsets? bottomSectionPadding; @override - ScrollableWithBottomSectionState createState() => - ScrollableWithBottomSectionState(); + ScrollableWithBottomSectionState createState() => ScrollableWithBottomSectionState(); } -class ScrollableWithBottomSectionState - extends State { +class ScrollableWithBottomSectionState extends State { @override Widget build(BuildContext context) { - return LayoutBuilder(builder: (context, constraints) { - return SingleChildScrollView( - // physics: - // const AlwaysScrollableScrollPhysics(), // const NeverScrollableScrollPhysics(), // - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.heightConstraints().maxHeight), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: widget.contentPadding ?? - EdgeInsets.only(left: 20, right: 20), - child: widget.content, - ), - Padding( - padding: widget.bottomSectionPadding ?? - EdgeInsets.only(bottom: 20, right: 20, left: 20), - child: widget.bottomSection) - ], + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: widget.contentPadding ?? EdgeInsets.only(left: 20, right: 20), + child: widget.content, + ), ), ), - ); - }); + Padding( + padding: widget.bottomSectionPadding?.copyWith(top: 10) ?? + EdgeInsets.only(top: 10, bottom: 20, right: 20, left: 20), + child: widget.bottomSection, + ), + ], + ); } } diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 14033b368..b78d831a4 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -27,11 +27,25 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { final SettingsStore _settingsStore; - bool get hasSeedPhraseLengthOption => - type == WalletType.bitcoinCash || - type == WalletType.ethereum || - type == WalletType.polygon || - type == WalletType.solana; + bool get hasSeedPhraseLengthOption { + // convert to switch case so that it give a syntax error when adding a new wallet type + // thus we don't forget about it + switch (type) { + case WalletType.ethereum: + case WalletType.bitcoinCash: + case WalletType.polygon: + case WalletType.solana: + return true; + case WalletType.monero: + case WalletType.none: + case WalletType.bitcoin: + case WalletType.litecoin: + case WalletType.haven: + case WalletType.nano: + case WalletType.banano: + return false; + } + } bool get hasSeedTypeOption => type == WalletType.monero; diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 1ce2cdb14..615afc2d6 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -15,7 +15,8 @@ class UnspentCoinsListViewModel = UnspentCoinsListViewModelBase with _$UnspentCo abstract class UnspentCoinsListViewModelBase with Store { UnspentCoinsListViewModelBase( {required this.wallet, required Box unspentCoinsInfo}) - : _unspentCoinsInfo = unspentCoinsInfo { + : _unspentCoinsInfo = unspentCoinsInfo, + _items = ObservableList() { _updateUnspentCoinsInfo(); _updateUnspents(); } @@ -23,7 +24,8 @@ abstract class UnspentCoinsListViewModelBase with Store { WalletBase wallet; final Box _unspentCoinsInfo; - final ObservableList _items = ObservableList(); + @observable + ObservableList _items; @computed ObservableList get items => _items; diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index 7cd0d3a76..ccaa18605 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -21,9 +21,7 @@ abstract class WalletKeysViewModelBase with Store { : title = _appStore.wallet!.type == WalletType.bitcoin || _appStore.wallet!.type == WalletType.lightning || _appStore.wallet!.type == WalletType.litecoin || - _appStore.wallet!.type == WalletType.bitcoinCash || - _appStore.wallet!.type == WalletType.ethereum || - _appStore.wallet!.type == WalletType.polygon + _appStore.wallet!.type == WalletType.bitcoinCash ? S.current.wallet_seed : S.current.wallet_keys, _restoreHeight = _appStore.wallet!.walletInfo.restoreHeight, diff --git a/tool/configure.dart b/tool/configure.dart index 7fad144b6..ff10312fa 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -824,10 +824,6 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';"; const bitcoinCashContent = """ abstract class BitcoinCash { - String getMnemonic(int? strength); - - Uint8List getSeedFromMnemonic(String seed); - String getCashAddrFormat(String address); WalletService createBitcoinCashWalletService(