Generic fixes (#1304)
* fix mobx no element error * fix mobx issue * Remove unused code * Enhance error handling for monero sync failure case * Separate litecoin mnemonic exception from bitcoin * - Enable onramper for polygon - Add Kaspa validation * Set null as the default length of address validation * Modify EVM fee text [skip ci] * Add seed length option to polygon * Add digibyte * Update configure_cake_wallet.sh and fix conflicts * Pin bottom section * Fix Solana missing isTestnet param
Omar Hatem committed
Feb 23, 2024 at 19:09 UTC
cbc0c3afd6bcb5999bc0928d9aa209e34d674849
20 files changed
+84
-70
.gitignore
+1
@@ -86,6 +86,7 @@ cw_monero/cw_monero/android/.cxx/
86
**/*.g.dart
87
88
android/key.properties
89
+android/app/key.jks
90
91
**/tool/.secrets-prod.json
92
**/tool/.secrets-test.json
assets/images/digibyte.png
Binary files /dev/null and b/assets/images/digibyte.png differ
configure_cake_wallet.sh
+1
@@ -30,6 +30,7 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build
30
cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
31
cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
32
cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
33
+cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
34
cd cw_ethereum && flutter pub get && cd ..
35
cd cw_polygon && flutter pub get && cd ..
36
flutter packages pub run build_runner build --delete-conflicting-outputs
cw_bitcoin/lib/bitcoin_wallet_service.dart
+1
-1
@@ -1,7 +1,7 @@
1
import 'dart:io';
2
import 'package:bitcoin_base/bitcoin_base.dart';
3
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
4
-import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart';
4
+import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
5
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
6
import 'package:cw_core/unspent_coins_info.dart';
7
import 'package:cw_core/wallet_base.dart';
cw_bitcoin/lib/litecoin_wallet_service.dart
+2
-2
@@ -2,7 +2,7 @@ import 'dart:io';
2
import 'package:cw_core/unspent_coins_info.dart';
3
import 'package:hive/hive.dart';
4
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
5
-import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart';
5
+import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
6
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
7
import 'package:cw_bitcoin/litecoin_wallet.dart';
8
import 'package:cw_core/wallet_service.dart';
@@ -101,7 +101,7 @@ class LitecoinWalletService extends WalletService<
101
Future<LitecoinWallet> restoreFromSeed(
102
BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async {
103
if (!validateMnemonic(credentials.mnemonic)) {
104
- throw BitcoinMnemonicIsIncorrectException();
104
+ throw LitecoinMnemonicIsIncorrectException();
105
}
106
107
final wallet = await LitecoinWalletBase.create(
cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart
renamed
+6
@@ -3,3 +3,9 @@ class BitcoinMnemonicIsIncorrectException implements Exception {
3
String toString() =>
4
'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.';
5
}
6
+
7
+class LitecoinMnemonicIsIncorrectException implements Exception {
8
+ @override
9
+ String toString() =>
10
+ 'Litecoin mnemonic has incorrect format. Mnemonic should contain 24 words separated by space.';
11
+}
cw_core/lib/crypto_currency.dart
+6
-3
@@ -9,7 +9,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
9
required this.decimals,
10
this.fullName,
11
this.iconPath,
12
- this.tag, this.enabled = false,
12
+ this.tag,
13
+ this.enabled = false,
14
})
15
: super(title: title, raw: raw);
16
@@ -100,6 +101,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
101
CryptoCurrency.usdtPoly,
102
CryptoCurrency.usdcEPoly,
103
CryptoCurrency.kaspa,
104
+ CryptoCurrency.digibyte,
105
];
106
107
static const havenCurrencies = [
@@ -211,8 +213,9 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
213
static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29);
214
static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6);
215
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);
214
- static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kaspa', iconPath: 'assets/images/kaspa_icon.png', decimals: 8);
215
- static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6);
216
+ static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8);
217
+ static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8);
218
+ static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6);
219
220
221
static final Map<int, CryptoCurrency> _rawCurrencyMap =
cw_evm/lib/evm_chain_wallet_addresses.dart
+1
@@ -14,6 +14,7 @@ abstract class EVMChainWalletAddressesBase extends WalletAddresses with Store {
14
super(walletInfo);
15
16
@override
17
+ @observable
18
String address;
19
20
@override
cw_monero/lib/monero_wallet.dart
+12
-8
@@ -576,15 +576,19 @@ abstract class MoneroWalletBase
576
return;
577
}
578
579
- final height = _getHeightByDate(walletInfo.date);
580
-
581
- if (height > MIN_RESTORE_HEIGHT) {
582
- monero_wallet.setRecoveringFromSeed(isRecovery: true);
583
- monero_wallet.setRefreshFromBlockHeight(height: height);
584
- return;
579
+ int height = 0;
580
+ try {
581
+ height = _getHeightByDate(walletInfo.date);
582
+ } catch (e, s) {
583
+ onError?.call(FlutterErrorDetails(
584
+ exception: e,
585
+ stack: s,
586
+ library: this.runtimeType.toString(),
587
+ ));
588
}
589
587
- throw Exception("height isn't > $MIN_RESTORE_HEIGHT!");
590
+ monero_wallet.setRecoveringFromSeed(isRecovery: true);
591
+ monero_wallet.setRefreshFromBlockHeight(height: height);
592
}
593
594
int _getHeightDistance(DateTime date) {
@@ -600,7 +604,7 @@ abstract class MoneroWalletBase
604
final heightDistance = _getHeightDistance(date);
605
606
if (nodeHeight <= 0) {
603
- // the node returned 0 (an error state), so lets just restore from cache:
607
+ // the node returned 0 (an error state)
608
throw Exception("nodeHeight is <= 0!");
609
}
610
cw_solana/lib/default_spl_tokens.dart
-2
@@ -25,7 +25,6 @@ class DefaultSPLTokens {
25
mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk',
26
decimal: 6,
27
mint: 'soEth',
28
- enabled: true,
28
iconPath: 'assets/images/eth_icon.png',
29
),
30
SPLToken(
@@ -34,7 +33,6 @@ class DefaultSPLTokens {
33
mintAddress: 'So11111111111111111111111111111111111111112',
34
decimal: 9,
35
mint: 'WSOL',
37
- enabled: true,
36
iconPath: 'assets/images/sol_icon.png',
37
),
38
SPLToken(
cw_solana/lib/solana_wallet_service.dart
+5
-3
@@ -19,7 +19,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
19
final Box<WalletInfo> walletInfoSource;
20
21
@override
22
- Future<SolanaWallet> create(SolanaNewWalletCredentials credentials) async {
22
+ Future<SolanaWallet> create(SolanaNewWalletCredentials credentials, {bool? isTestnet}) async {
23
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
24
25
final mnemonic = bip39.generateMnemonic(strength: strength);
@@ -67,7 +67,8 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
67
}
68
69
@override
70
- Future<SolanaWallet> restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials) async {
70
+ Future<SolanaWallet> restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials,
71
+ {bool? isTestnet}) async {
72
final wallet = SolanaWallet(
73
password: credentials.password!,
74
privateKey: credentials.privateKey,
@@ -82,7 +83,8 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
83
}
84
85
@override
85
- Future<SolanaWallet> restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials) async {
86
+ Future<SolanaWallet> restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials,
87
+ {bool? isTestnet}) async {
88
if (!bip39.validateMnemonic(credentials.mnemonic)) {
89
throw SolanaMnemonicIsIncorrectException();
90
}
lib/bitcoin_cash/cw_bitcoin_cash.dart
-6
@@ -1,12 +1,6 @@
1
part of 'bitcoin_cash.dart';
2
3
class CWBitcoinCash extends BitcoinCash {
4
- @override
5
- String getMnemonic(int? strength) => Mnemonic.generate();
6
-
7
- @override
8
- Uint8List getSeedFromMnemonic(String seed) => Mnemonic.toSeed(seed);
9
-
4
@override
5
String getCashAddrFormat(String address) => AddressUtils.getCashAddrFormat(address);
6
lib/core/address_validator.dart
+2
-2
@@ -257,9 +257,9 @@ class AddressValidator extends TextValidator {
257
case CryptoCurrency.near:
258
return [64];
259
case CryptoCurrency.btcln:
260
- return null;
260
+ case CryptoCurrency.kaspa:
261
default:
262
- return [];
262
+ return null;
263
}
264
}
265
lib/entities/provider_types.dart
+2
-2
@@ -66,7 +66,7 @@ class ProvidersHelper {
66
case WalletType.bitcoinCash:
67
return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood];
68
case WalletType.polygon:
69
- return [ProviderType.askEachTime, ProviderType.dfx];
69
+ return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx];
70
case WalletType.solana:
71
return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood];
72
case WalletType.none:
@@ -89,7 +89,7 @@ class ProvidersHelper {
89
case WalletType.bitcoinCash:
90
return [ProviderType.askEachTime, ProviderType.moonpaySell];
91
case WalletType.polygon:
92
- return [ProviderType.askEachTime, ProviderType.dfx];
92
+ return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx];
93
case WalletType.solana:
94
return [
95
ProviderType.askEachTime,
lib/src/screens/send/send_page.dart
+4
-1
@@ -1,6 +1,7 @@
1
import 'package:cake_wallet/core/auth_service.dart';
2
import 'package:cake_wallet/entities/fiat_currency.dart';
3
import 'package:cake_wallet/entities/template.dart';
4
+import 'package:cake_wallet/reactions/wallet_connect.dart';
5
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
6
import 'package:cake_wallet/src/screens/send/widgets/send_card.dart';
7
import 'package:cake_wallet/src/widgets/add_template_button.dart';
@@ -420,7 +421,9 @@ class SendPage extends BasePage {
421
amount: S.of(_dialogContext).send_amount,
422
amountValue: sendViewModel.pendingTransaction!.amountFormatted,
423
fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
423
- fee: S.of(_dialogContext).send_fee,
424
+ fee: isEVMCompatibleChain(sendViewModel.walletType)
425
+ ? S.of(_dialogContext).send_estimated_fee
426
+ : S.of(_dialogContext).send_fee,
427
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
428
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
429
outputs: sendViewModel.outputs,
lib/src/widgets/scollable_with_bottom_section.dart
+17
-26
@@ -14,37 +14,28 @@ class ScrollableWithBottomSection extends StatefulWidget {
14
final EdgeInsets? bottomSectionPadding;
15
16
@override
17
- ScrollableWithBottomSectionState createState() =>
18
- ScrollableWithBottomSectionState();
17
+ ScrollableWithBottomSectionState createState() => ScrollableWithBottomSectionState();
18
}
19
21
-class ScrollableWithBottomSectionState
22
- extends State<ScrollableWithBottomSection> {
20
+class ScrollableWithBottomSectionState extends State<ScrollableWithBottomSection> {
21
@override
22
Widget build(BuildContext context) {
25
- return LayoutBuilder(builder: (context, constraints) {
26
- return SingleChildScrollView(
27
- // physics:
28
- // const AlwaysScrollableScrollPhysics(), // const NeverScrollableScrollPhysics(), //
29
- child: ConstrainedBox(
30
- constraints: BoxConstraints(
31
- minHeight: constraints.heightConstraints().maxHeight),
32
- child: Column(
33
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
34
- children: <Widget>[
35
- Padding(
36
- padding: widget.contentPadding ??
37
- EdgeInsets.only(left: 20, right: 20),
38
- child: widget.content,
39
- ),
40
- Padding(
41
- padding: widget.bottomSectionPadding ??
42
- EdgeInsets.only(bottom: 20, right: 20, left: 20),
43
- child: widget.bottomSection)
44
- ],
23
+ return Column(
24
+ children: [
25
+ Expanded(
26
+ child: SingleChildScrollView(
27
+ child: Padding(
28
+ padding: widget.contentPadding ?? EdgeInsets.only(left: 20, right: 20),
29
+ child: widget.content,
30
+ ),
31
),
32
),
47
- );
48
- });
33
+ Padding(
34
+ padding: widget.bottomSectionPadding?.copyWith(top: 10) ??
35
+ EdgeInsets.only(top: 10, bottom: 20, right: 20, left: 20),
36
+ child: widget.bottomSection,
37
+ ),
38
+ ],
39
+ );
40
}
41
}
lib/view_model/advanced_privacy_settings_view_model.dart
+19
-5
@@ -27,11 +27,25 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
27
28
final SettingsStore _settingsStore;
29
30
- bool get hasSeedPhraseLengthOption =>
31
- type == WalletType.bitcoinCash ||
32
- type == WalletType.ethereum ||
33
- type == WalletType.polygon ||
34
- type == WalletType.solana;
30
+ bool get hasSeedPhraseLengthOption {
31
+ // convert to switch case so that it give a syntax error when adding a new wallet type
32
+ // thus we don't forget about it
33
+ switch (type) {
34
+ case WalletType.ethereum:
35
+ case WalletType.bitcoinCash:
36
+ case WalletType.polygon:
37
+ case WalletType.solana:
38
+ return true;
39
+ case WalletType.monero:
40
+ case WalletType.none:
41
+ case WalletType.bitcoin:
42
+ case WalletType.litecoin:
43
+ case WalletType.haven:
44
+ case WalletType.nano:
45
+ case WalletType.banano:
46
+ return false;
47
+ }
48
+ }
49
50
bool get hasSeedTypeOption => type == WalletType.monero;
51
lib/view_model/unspent_coins/unspent_coins_list_view_model.dart
+4
-2
@@ -15,7 +15,8 @@ class UnspentCoinsListViewModel = UnspentCoinsListViewModelBase with _$UnspentCo
15
abstract class UnspentCoinsListViewModelBase with Store {
16
UnspentCoinsListViewModelBase(
17
{required this.wallet, required Box<UnspentCoinsInfo> unspentCoinsInfo})
18
- : _unspentCoinsInfo = unspentCoinsInfo {
18
+ : _unspentCoinsInfo = unspentCoinsInfo,
19
+ _items = ObservableList<UnspentCoinsItem>() {
20
_updateUnspentCoinsInfo();
21
_updateUnspents();
22
}
@@ -23,7 +24,8 @@ abstract class UnspentCoinsListViewModelBase with Store {
24
WalletBase wallet;
25
final Box<UnspentCoinsInfo> _unspentCoinsInfo;
26
26
- final ObservableList<UnspentCoinsItem> _items = ObservableList();
27
+ @observable
28
+ ObservableList<UnspentCoinsItem> _items;
29
30
@computed
31
ObservableList<UnspentCoinsItem> get items => _items;
lib/view_model/wallet_keys_view_model.dart
+1
-3
@@ -20,9 +20,7 @@ abstract class WalletKeysViewModelBase with Store {
20
WalletKeysViewModelBase(this._appStore)
21
: title = _appStore.wallet!.type == WalletType.bitcoin ||
22
_appStore.wallet!.type == WalletType.litecoin ||
23
- _appStore.wallet!.type == WalletType.bitcoinCash ||
24
- _appStore.wallet!.type == WalletType.ethereum ||
25
- _appStore.wallet!.type == WalletType.polygon
23
+ _appStore.wallet!.type == WalletType.bitcoinCash
24
? S.current.wallet_seed
25
: S.current.wallet_keys,
26
_restoreHeight = _appStore.wallet!.walletInfo.restoreHeight,
tool/configure.dart
-4
@@ -729,10 +729,6 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
729
const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';";
730
const bitcoinCashContent = """
731
abstract class BitcoinCash {
732
- String getMnemonic(int? strength);
733
-
734
- Uint8List getSeedFromMnemonic(String seed);
735
-
732
String getCashAddrFormat(String address);
733
734
WalletService createBitcoinCashWalletService(