Fixed issues for linter and analyzer
M committed
Jan 8, 2020 at 14:26 UTC
78ec11de47808b62fd15e15507cbc611a2d201c9
168 files changed
+2262
-1959
analysis_options.yaml
+3
-10
@@ -5,17 +5,14 @@ analyzer:
5
implicit-casts: false
6
implicit-dynamic: false
7
exclude:
8
- - **/*.yaml
9
- - build/**
10
- - **/*.g.dart
11
- - lib/generated/*.dart
8
+ - "build/**"
9
+ - "**/*.g.dart"
10
+ - "lib/generated/*.dart"
11
12
linter:
13
rules:
14
- always_declare_return_types
16
- - always_specify_types
15
- annotate_overrides
18
- - avoid_as
16
- avoid_empty_else
17
- avoid_init_to_null
18
- avoid_return_types_on_setters
@@ -48,17 +45,13 @@ linter:
45
- prefer_final_fields
46
- prefer_final_locals
47
- prefer_is_not_empty
51
- - public_member_api_docs
48
- slash_for_doc_comments
49
- sort_constructors_first
50
- sort_unnamed_constructors_first
55
- - super_goes_last
51
- test_types_in_equals
52
- throw_in_finally
58
- - type_annotate_public_apis
53
- type_init_formals
54
- unawaited_futures
61
- - unnecessary_brace_in_string_interp
55
- unnecessary_getters_setters
56
- unrelated_type_equality_checks
57
- valid_regexps
\ No newline at end of file
cw_monero/lib/account_list.dart
+14
-9
@@ -26,7 +26,7 @@ final accountSetLabelNative = moneroApi
26
.lookup<NativeFunction<account_set_label>>('account_set_label_row')
27
.asFunction<AccountSetLabel>();
28
29
-refreshAccounts() => accountRefreshNative();
29
+void refreshAccounts() => accountRefreshNative();
30
31
List<AccountRow> getAllAccount() {
32
final size = accountSizeNative();
@@ -38,24 +38,29 @@ List<AccountRow> getAllAccount() {
38
.toList();
39
}
40
41
-addAccountSync({String label}) {
41
+void addAccountSync({String label}) {
42
final labelPointer = Utf8.toUtf8(label);
43
accountAddNewNative(labelPointer);
44
free(labelPointer);
45
}
46
47
-setLabelForAccountSync({int accountIndex, String label}) {
47
+void setLabelForAccountSync({int accountIndex, String label}) {
48
final labelPointer = Utf8.toUtf8(label);
49
accountSetLabelNative(accountIndex, labelPointer);
50
free(labelPointer);
51
}
52
53
-_addAccount(String label) => addAccountSync(label: label);
53
+void _addAccount(String label) => addAccountSync(label: label);
54
55
-_setLabelForAccount(Map args) => setLabelForAccountSync(
56
- label: args['label'], accountIndex: args['accountIndex']);
55
+void _setLabelForAccount(Map<String, dynamic> args) {
56
+ final label = args['label'] as String;
57
+ final accountIndex = args['accountIndex'] as int;
58
58
-Future addAccount({String label}) async => compute(_addAccount, label);
59
+ setLabelForAccountSync(label: label, accountIndex: accountIndex);
60
+}
61
+
62
+Future<void> addAccount({String label}) async => compute(_addAccount, label);
63
60
-Future setLabelForAccount({int accountIndex, String label}) async => compute(
61
- _setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
64
+Future<void> setLabelForAccount({int accountIndex, String label}) async =>
65
+ compute(
66
+ _setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
cw_monero/lib/exceptions/connection_to_node_exception.dart
+2
-2
@@ -1,5 +1,5 @@
1
class ConnectionToNodeException implements Exception {
2
- final String message;
3
-
2
ConnectionToNodeException({this.message});
3
+
4
+ final String message;
5
}
\ No newline at end of file
cw_monero/lib/exceptions/creation_transaction_exception.dart
+2
-2
@@ -1,7 +1,7 @@
1
class CreationTransactionException implements Exception {
2
- final String message;
3
-
2
CreationTransactionException({this.message});
3
+
4
+ final String message;
5
6
@override
7
String toString() => message;
cw_monero/lib/exceptions/setup_wallet_exception.dart
+2
-2
@@ -1,5 +1,5 @@
1
class SetupWalletException implements Exception {
2
- final String message;
3
-
2
SetupWalletException({this.message});
3
+
4
+ final String message;
5
}
\ No newline at end of file
cw_monero/lib/exceptions/wallet_creation_exception.dart
+2
-2
@@ -1,5 +1,5 @@
1
class WalletCreationException implements Exception {
2
- final String message;
3
-
2
WalletCreationException({this.message});
3
+
4
+ final String message;
5
}
\ No newline at end of file
cw_monero/lib/exceptions/wallet_restore_from_keys_exception.dart
+2
-2
@@ -1,5 +1,5 @@
1
class WalletRestoreFromKeysException implements Exception {
2
- final String message;
3
-
2
WalletRestoreFromKeysException({this.message});
3
+
4
+ final String message;
5
}
\ No newline at end of file
cw_monero/lib/exceptions/wallet_restore_from_seed_exception.dart
+2
-2
@@ -1,5 +1,5 @@
1
class WalletRestoreFromSeedException implements Exception {
2
- final String message;
3
-
2
WalletRestoreFromSeedException({this.message});
3
+
4
+ final String message;
5
}
\ No newline at end of file
cw_monero/lib/structs/pending_transaction.dart
+2
-2
@@ -14,10 +14,10 @@ class PendingTransactionRaw extends Struct {
14
}
15
16
class PendingTransactionDescription {
17
+ PendingTransactionDescription({this.amount, this.fee, this.hash, this.pointerAddress});
18
+
19
final int amount;
20
final int fee;
21
final String hash;
22
final int pointerAddress;
21
-
22
- PendingTransactionDescription({this.amount, this.fee, this.hash, this.pointerAddress});
23
}
\ No newline at end of file
cw_monero/lib/subaddress_list.dart
+20
-10
@@ -26,7 +26,7 @@ final subaddrressSetLabelNative = moneroApi
26
.lookup<NativeFunction<subaddress_set_label>>('subaddress_set_label')
27
.asFunction<SubaddressSetLabel>();
28
29
-refreshSubaddresses({int accountIndex}) =>
29
+void refreshSubaddresses({int accountIndex}) =>
30
subaddressRefreshNative(accountIndex);
31
32
List<SubaddressRow> getAllSubaddresses() {
@@ -40,25 +40,35 @@ List<SubaddressRow> getAllSubaddresses() {
40
.toList();
41
}
42
43
-addSubaddressSync({int accountIndex, String label}) {
43
+void addSubaddressSync({int accountIndex, String label}) {
44
final labelPointer = Utf8.toUtf8(label);
45
subaddrressAddNewNative(accountIndex, labelPointer);
46
free(labelPointer);
47
}
48
49
-setLabelForSubaddressSync({int accountIndex, int addressIndex, String label}) {
49
+void setLabelForSubaddressSync(
50
+ {int accountIndex, int addressIndex, String label}) {
51
final labelPointer = Utf8.toUtf8(label);
52
+
53
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
54
free(labelPointer);
55
}
56
55
-_addSubaddress(Map args) =>
56
- addSubaddressSync(accountIndex: args['accountIndex'], label: args['label']);
57
+void _addSubaddress(Map<String, dynamic> args) {
58
+ final label = args['label'] as String;
59
+ final accountIndex = args['accountIndex'] as int;
60
58
-_setLabelForSubaddress(Map args) => setLabelForSubaddressSync(
59
- accountIndex: args['accountIndex'],
60
- addressIndex: args['addressIndex'],
61
- label: args['label']);
61
+ addSubaddressSync(accountIndex: accountIndex, label: label);
62
+}
63
+
64
+void _setLabelForSubaddress(Map<String, dynamic> args) {
65
+ final label = args['label'] as String;
66
+ final accountIndex = args['accountIndex'] as int;
67
+ final addressIndex = args['addressIndex'] as int;
68
+
69
+ setLabelForSubaddressSync(
70
+ accountIndex: accountIndex, addressIndex: addressIndex, label: label);
71
+}
72
73
Future addSubaddress({int accountIndex, String label}) async =>
74
compute(_addSubaddress, {'accountIndex': accountIndex, 'label': label});
@@ -69,4 +79,4 @@ Future setLabelForSubaddress(
79
'accountIndex': accountIndex,
80
'addressIndex': addressIndex,
81
'label': label
72
- });
\ No newline at end of file
82
+ });
cw_monero/lib/transaction_history.dart
+17
-10
@@ -29,7 +29,7 @@ final transactionCommitNative = moneroApi
29
.lookup<NativeFunction<transaction_commit>>('transaction_commit')
30
.asFunction<TransactionCommit>();
31
32
-refreshTransactions() => transactionsRefreshNative();
32
+void refreshTransactions() => transactionsRefreshNative();
33
34
int countOfTransactions() => transactionsCountNative();
35
@@ -84,10 +84,10 @@ PendingTransactionDescription createTransactionSync(
84
pointerAddress: pendingTransactionRawPointer.address);
85
}
86
87
-commitTransactionFromPointerAddress({int address}) => commitTransaction(
87
+void commitTransactionFromPointerAddress({int address}) => commitTransaction(
88
transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
89
90
-commitTransaction({Pointer<PendingTransactionRaw> transactionPointer}) {
90
+void commitTransaction({Pointer<PendingTransactionRaw> transactionPointer}) {
91
final errorMessagePointer = allocate<Utf8Box>();
92
final isCommited =
93
transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
@@ -99,13 +99,20 @@ commitTransaction({Pointer<PendingTransactionRaw> transactionPointer}) {
99
}
100
}
101
102
-PendingTransactionDescription _createTransactionSync(Map args) =>
103
- createTransactionSync(
104
- address: args['address'],
105
- paymentId: args['paymentId'],
106
- amount: args['amount'],
107
- priorityRaw: args['priorityRaw'],
108
- accountIndex: args['accountIndex']);
102
+PendingTransactionDescription _createTransactionSync(Map args) {
103
+ final address = args['address'] as String;
104
+ final paymentId = args['paymentId'] as String;
105
+ final amount = args['amount'] as String;
106
+ final priorityRaw = args['priorityRaw'] as int;
107
+ final accountIndex = args['accountIndex'] as int;
108
+
109
+ return createTransactionSync(
110
+ address: address,
111
+ paymentId: paymentId,
112
+ amount: amount,
113
+ priorityRaw: priorityRaw,
114
+ accountIndex: accountIndex);
115
+}
116
117
Future<PendingTransactionDescription> createTransaction(
118
{String address,
cw_monero/lib/wallet.dart
+31
-20
@@ -179,23 +179,23 @@ bool setupNodeSync(
179
return isSetupNode;
180
}
181
182
-startRefreshSync() => startRefreshNative();
182
+void startRefreshSync() => startRefreshNative();
183
184
Future<bool> connectToNode() async => connecToNodeNative() != 0;
185
186
-setRefreshFromBlockHeight({int height}) =>
186
+void setRefreshFromBlockHeight({int height}) =>
187
setRefreshFromBlockHeightNative(height);
188
189
-setRecoveringFromSeed({bool isRecovery}) =>
189
+void setRecoveringFromSeed({bool isRecovery}) =>
190
setRecoveringFromSeedNative(_boolToInt(isRecovery));
191
192
-storeSync() {
192
+void storeSync() {
193
final pathPointer = Utf8.toUtf8('');
194
storeNative(pathPointer);
195
free(pathPointer);
196
}
197
198
-closeCurrentWallet() => closeCurrentWalletNative();
198
+void closeCurrentWallet() => closeCurrentWalletNative();
199
200
String getSecretViewKey() =>
201
convertUTF8ToString(pointer: getSecretViewKeyNative());
@@ -213,8 +213,8 @@ Timer _updateSyncInfoTimer;
213
214
int _lastKnownBlockHeight = 0;
215
216
-setListeners(Future Function(int) onNewBlock, Future Function() onNeedToRefresh,
217
- Future Function() onNewTransaction) {
216
+void setListeners(Future Function(int) onNewBlock,
217
+ Future Function() onNeedToRefresh, Future Function() onNewTransaction) {
218
if (_updateSyncInfoTimer != null) {
219
_updateSyncInfoTimer.cancel();
220
}
@@ -240,25 +240,36 @@ setListeners(Future Function(int) onNewBlock, Future Function() onNeedToRefresh,
240
setListenerNative();
241
}
242
243
-closeListeners() {
243
+void closeListeners() {
244
if (_updateSyncInfoTimer != null) {
245
_updateSyncInfoTimer.cancel();
246
}
247
}
248
249
-onStartup() => onStartupNative();
249
+void onStartup() => onStartupNative();
250
251
-_storeSync(_) => storeSync();
252
-bool _setupNodeSync(Map args) => setupNodeSync(
253
- address: args['address'],
254
- login: args['login'] ?? '',
255
- password: args['password'] ?? '',
256
- useSSL: args['useSSL'],
257
- isLightWallet: args['isLightWallet']);
258
-bool _isConnected(_) => isConnectedSync();
259
-int _getNodeHeight(_) => getNodeHeightSync();
251
+void _storeSync(Object _) => storeSync();
252
261
-startRefresh() => startRefreshSync();
253
+bool _setupNodeSync(Map args) {
254
+ final address = args['address'] as String;
255
+ final login = (args['login'] ?? '') as String;
256
+ final password = (args['password'] ?? '') as String;
257
+ final useSSL = args['useSSL'] as bool;
258
+ final isLightWallet = args['isLightWallet'] as bool;
259
+
260
+ return setupNodeSync(
261
+ address: address,
262
+ login: login,
263
+ password: password,
264
+ useSSL: useSSL,
265
+ isLightWallet: isLightWallet);
266
+}
267
+
268
+bool _isConnected(Object _) => isConnectedSync();
269
+
270
+int _getNodeHeight(Object _) => getNodeHeightSync();
271
+
272
+void startRefresh() => startRefreshSync();
273
274
Future setupNode(
275
{String address,
@@ -280,4 +291,4 @@ Future<bool> isConnected() => compute(_isConnected, 0);
291
292
Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
293
283
-rescanBlockchainAsync() => rescanBlockchainAsyncNative();
\ No newline at end of file
294
+void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
cw_monero/lib/wallet_manager.dart
+41
-23
@@ -31,7 +31,7 @@ final loadWalletNative = moneroApi
31
.lookup<NativeFunction<load_wallet>>('load_wallet')
32
.asFunction<LoadWallet>();
33
34
-createWalletSync(
34
+void createWalletSync(
35
{String path,
36
String password,
37
String language = 'English',
@@ -63,7 +63,7 @@ bool isWalletExistSync({String path}) {
63
return isExist;
64
}
65
66
-restoreWalletFromSeedSync(
66
+void restoreWalletFromSeedSync(
67
{String path,
68
String password,
69
String seed,
@@ -92,7 +92,7 @@ restoreWalletFromSeedSync(
92
}
93
}
94
95
-restoreWalletFromKeysSync(
95
+void restoreWalletFromKeysSync(
96
{String path,
97
String password,
98
String language = 'English',
@@ -133,7 +133,7 @@ restoreWalletFromKeysSync(
133
}
134
}
135
136
-loadWallet({String path, String password, int nettype = 0}) {
136
+void loadWallet({String path, String password, int nettype = 0}) {
137
final pathPointer = Utf8.toUtf8(path);
138
final passwordPointer = Utf8.toUtf8(password);
139
@@ -142,34 +142,52 @@ loadWallet({String path, String password, int nettype = 0}) {
142
free(passwordPointer);
143
}
144
145
-_createWallet(args) =>
146
- createWalletSync(path: args['path'], password: args['password']);
145
+void _createWallet(Map<String, dynamic> args) {
146
+ final path = args['path'] as String;
147
+ final password = args['password'] as String;
148
148
-_restoreFromSeed(args) => restoreWalletFromSeedSync(
149
- path: args['path'],
150
- password: args['password'],
151
- seed: args['seed'],
152
- restoreHeight: args['restoreHeight']);
149
+ createWalletSync(path: path, password: password);
150
+}
151
+
152
+void _restoreFromSeed(Map<String, dynamic> args) {
153
+ final path = args['path'] as String;
154
+ final password = args['password'] as String;
155
+ final seed = args['seed'] as String;
156
+ final restoreHeight = args['restoreHeight'] as int;
157
154
-_restoreFromKeys(args) => restoreWalletFromKeysSync(
155
- path: args['path'],
156
- password: args['password'],
157
- restoreHeight: args['restoreHeight'],
158
- address: args['address'],
159
- viewKey: args['viewKey'],
160
- spendKey: args['spendKey']);
158
+ restoreWalletFromSeedSync(
159
+ path: path, password: password, seed: seed, restoreHeight: restoreHeight);
160
+}
161
+
162
+void _restoreFromKeys(Map<String, dynamic> args) {
163
+ final path = args['path'] as String;
164
+ final password = args['password'] as String;
165
+ final restoreHeight = args['restoreHeight'] as int;
166
+ final address = args['address'] as String;
167
+ final viewKey = args['viewKey'] as String;
168
+ final spendKey = args['spendKey'] as String;
169
+
170
+ restoreWalletFromKeysSync(
171
+ path: path,
172
+ password: password,
173
+ restoreHeight: restoreHeight,
174
+ address: address,
175
+ viewKey: viewKey,
176
+ spendKey: spendKey);
177
+}
178
162
-_openWallet(Map args) async =>
179
+Future<void> _openWallet(Map<String, String> args) async =>
180
loadWallet(path: args['path'], password: args['password']);
181
182
bool _isWalletExist(String path) => isWalletExistSync(path: path);
183
167
-openWallet({String path, String password, int nettype = 0}) async =>
184
+void openWallet({String path, String password, int nettype = 0}) async =>
185
loadWallet(path: path, password: password);
186
170
-Future openWalletAsync(Map args) async => compute(_openWallet, args);
187
+Future<void> openWalletAsync(Map<String, String> args) async =>
188
+ compute(_openWallet, args);
189
172
-Future createWallet(
190
+Future<void> createWallet(
191
{String path,
192
String password,
193
String language = 'English',
@@ -215,4 +233,4 @@ Future restoreFromKeys(
233
'restoreHeight': restoreHeight
234
});
235
218
-Future<bool> isWalletExist({String path}) => compute(_isWalletExist, path);
\ No newline at end of file
236
+Future<bool> isWalletExist({String path}) => compute(_isWalletExist, path);
lib/main.dart
+13
-11
@@ -6,7 +6,7 @@ import 'package:provider/provider.dart';
6
import 'package:flutter/material.dart';
7
import 'package:flutter/services.dart';
8
import 'package:hive/hive.dart';
9
-import 'package:cw_monero/wallet.dart' as moneroWallet;
9
+import 'package:cw_monero/wallet.dart' as monero_wallet;
10
import 'package:cake_wallet/router.dart';
11
import 'theme_changer.dart';
12
import 'themes.dart';
@@ -39,7 +39,7 @@ import 'package:cake_wallet/src/domain/common/language.dart';
39
void main() async {
40
WidgetsFlutterBinding.ensureInitialized();
41
42
- var appDir = await getApplicationDocumentsDirectory();
42
+ final appDir = await getApplicationDocumentsDirectory();
43
Hive.init(appDir.path);
44
Hive.registerAdapter(ContactAdapter(), 0);
45
Hive.registerAdapter(NodeAdapter(), 1);
@@ -50,18 +50,20 @@ void main() async {
50
51
final secureStorage = FlutterSecureStorage();
52
final transactionDescriptionsBoxKey = await getEncryptionKey(
53
- secureStorage: secureStorage, forKey: 'transactionDescriptionsBoxKey'); // FIXME: Unnamed constant
53
+ secureStorage: secureStorage,
54
+ forKey: 'transactionDescriptionsBoxKey'); // FIXME: Unnamed constant
55
final tradesBoxKey = await getEncryptionKey(
55
- secureStorage: secureStorage, forKey: 'tradesBoxKey'); // FIXME: Unnamed constant
56
+ secureStorage: secureStorage,
57
+ forKey: 'tradesBoxKey'); // FIXME: Unnamed constant
58
57
- var contacts = await Hive.openBox<Contact>(Contact.boxName);
58
- var nodes = await Hive.openBox<Node>(Node.boxName);
59
- var transactionDescriptions = await Hive.openBox<TransactionDescription>(
59
+ final contacts = await Hive.openBox<Contact>(Contact.boxName);
60
+ final nodes = await Hive.openBox<Node>(Node.boxName);
61
+ final transactionDescriptions = await Hive.openBox<TransactionDescription>(
62
TransactionDescription.boxName,
63
encryptionKey: transactionDescriptionsBoxKey);
62
- var trades =
64
+ final trades =
65
await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
64
- var walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
66
+ final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
67
68
final sharedPreferences = await SharedPreferences.getInstance();
69
final walletService = WalletService();
@@ -124,7 +126,7 @@ void main() async {
126
], child: CakeWalletApp()));
127
}
128
127
-initialSetup(
129
+Future<void> initialSetup(
130
{WalletListService walletListService,
131
SharedPreferences sharedPreferences,
132
Box<Node> nodes,
@@ -137,7 +139,7 @@ initialSetup(
139
sharedPreferences: sharedPreferences,
140
nodes: nodes);
141
await authStore.started();
140
- moneroWallet.onStartup();
142
+ monero_wallet.onStartup();
143
}
144
145
class CakeWalletApp extends StatelessWidget {
lib/router.dart
+64
-53
@@ -19,6 +19,10 @@ import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.da
19
import 'package:cake_wallet/src/domain/common/node.dart';
20
import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
21
import 'package:cake_wallet/src/domain/exchange/trade.dart';
22
+import 'package:cake_wallet/src/domain/monero/account.dart';
23
+import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
24
+import 'package:cake_wallet/src/domain/common/transaction_info.dart';
25
+import 'package:cake_wallet/src/domain/monero/subaddress.dart';
26
27
// MARK: Import stores
28
@@ -101,10 +105,10 @@ class Router {
105
Box<Trade> trades}) {
106
switch (settings.name) {
107
case Routes.welcome:
104
- return MaterialPageRoute(builder: (_) => createWelcomePage());
108
+ return MaterialPageRoute<void>(builder: (_) => createWelcomePage());
109
110
case Routes.newWalletFromWelcome:
107
- return CupertinoPageRoute(
111
+ return CupertinoPageRoute<void>(
112
builder: (_) => Provider(
113
create: (_) => UserStore(
114
accountService: UserService(
@@ -115,7 +119,7 @@ class Router {
119
Navigator.pushNamed(context, Routes.newWallet))));
120
121
case Routes.newWallet:
118
- return CupertinoPageRoute(
122
+ return CupertinoPageRoute<void>(
123
builder:
124
(_) =>
125
ProxyProvider<AuthenticationStore, WalletCreationStore>(
@@ -132,10 +136,10 @@ class Router {
136
Function(BuildContext, String) callback;
137
138
if (settings.arguments is Function(BuildContext, String)) {
135
- callback = settings.arguments;
139
+ callback = settings.arguments as Function(BuildContext, String);
140
}
141
138
- return CupertinoPageRoute(
142
+ return CupertinoPageRoute<void>(
143
builder: (_) => Provider(
144
create: (_) => UserStore(
145
accountService: UserService(
@@ -147,13 +151,14 @@ class Router {
151
fullscreenDialog: true);
152
153
case Routes.restoreOptions:
150
- return CupertinoPageRoute(builder: (_) => RestoreOptionsPage());
154
+ return CupertinoPageRoute<void>(builder: (_) => RestoreOptionsPage());
155
156
case Routes.restoreWalletOptions:
153
- return CupertinoPageRoute(builder: (_) => RestoreWalletOptionsPage());
157
+ return CupertinoPageRoute<void>(
158
+ builder: (_) => RestoreWalletOptionsPage());
159
160
case Routes.restoreWalletOptionsFromWelcome:
156
- return CupertinoPageRoute(
161
+ return CupertinoPageRoute<void>(
162
builder: (_) => Provider(
163
create: (_) => UserStore(
164
accountService: UserService(
@@ -164,14 +169,14 @@ class Router {
169
context, Routes.restoreWalletOptions))));
170
171
case Routes.seed:
167
- return MaterialPageRoute(
172
+ return MaterialPageRoute<void>(
173
builder: (_) => createSeedPage(
174
settingsStore: settingsStore,
175
walletService: walletService,
171
- callback: settings.arguments));
176
+ callback: settings.arguments as void Function()));
177
178
case Routes.restoreWalletFromSeed:
174
- return CupertinoPageRoute(
179
+ return CupertinoPageRoute<void>(
180
builder: (_) =>
181
ProxyProvider<AuthenticationStore, WalletRestorationStore>(
182
update: (_, authStore, __) => WalletRestorationStore(
@@ -184,7 +189,7 @@ class Router {
189
sharedPreferences: sharedPreferences)));
190
191
case Routes.restoreWalletFromKeys:
187
- return CupertinoPageRoute(
192
+ return CupertinoPageRoute<void>(
193
builder: (_) =>
194
ProxyProvider<AuthenticationStore, WalletRestorationStore>(
195
update: (_, authStore, __) => WalletRestorationStore(
@@ -197,7 +202,7 @@ class Router {
202
sharedPreferences: sharedPreferences)));
203
204
case Routes.dashboard:
200
- return CupertinoPageRoute(
205
+ return CupertinoPageRoute<void>(
206
builder: (_) => createDashboardPage(
207
walletService: walletService,
208
priceStore: priceStore,
@@ -207,7 +212,7 @@ class Router {
212
walletStore: walletStore));
213
214
case Routes.send:
210
- return CupertinoPageRoute(
215
+ return CupertinoPageRoute<void>(
216
fullscreenDialog: true,
217
builder: (_) => MultiProvider(providers: [
218
ProxyProvider<SettingsStore, BalanceStore>(
@@ -227,7 +232,7 @@ class Router {
232
], child: SendPage()));
233
234
case Routes.receive:
230
- return CupertinoPageRoute(
235
+ return CupertinoPageRoute<void>(
236
fullscreenDialog: true,
237
builder: (_) => MultiProvider(providers: [
238
Provider(
@@ -236,30 +241,30 @@ class Router {
241
], child: ReceivePage()));
242
243
case Routes.transactionDetails:
239
- return CupertinoPageRoute(
244
+ return CupertinoPageRoute<void>(
245
fullscreenDialog: true,
241
- builder: (_) =>
242
- TransactionDetailsPage(transactionInfo: settings.arguments));
246
+ builder: (_) => TransactionDetailsPage(
247
+ transactionInfo: settings.arguments as TransactionInfo));
248
249
case Routes.newSubaddress:
245
- return CupertinoPageRoute(
250
+ return CupertinoPageRoute<void>(
251
builder: (_) => Provider(
252
create: (_) =>
253
SubadrressCreationStore(walletService: walletService),
254
child: NewSubaddressPage()));
255
256
case Routes.disclaimer:
252
- return CupertinoPageRoute(builder: (_) => DisclaimerPage());
257
+ return CupertinoPageRoute<void>(builder: (_) => DisclaimerPage());
258
259
case Routes.readDisclaimer:
255
- return CupertinoPageRoute(
260
+ return CupertinoPageRoute<void>(
261
builder: (_) => DisclaimerPage(isReadOnly: true));
262
263
case Routes.seedAlert:
259
- return CupertinoPageRoute(builder: (_) => SeedAlert());
264
+ return CupertinoPageRoute<void>(builder: (_) => SeedAlert());
265
266
case Routes.walletList:
262
- return MaterialPageRoute(
267
+ return MaterialPageRoute<void>(
268
fullscreenDialog: true,
269
builder: (_) => Provider(
270
create: (_) => WalletListStore(
@@ -268,40 +273,43 @@ class Router {
273
child: WalletListPage()));
274
275
case Routes.auth:
271
- return MaterialPageRoute(
276
+ return MaterialPageRoute<void>(
277
fullscreenDialog: true,
278
builder: (_) => Provider(
279
create: (_) => AuthStore(
280
sharedPreferences: sharedPreferences,
281
userService: userService,
282
walletService: walletService),
278
- child: AuthPage(onAuthenticationFinished: settings.arguments),
283
+ child: AuthPage(
284
+ onAuthenticationFinished:
285
+ settings.arguments as OnAuthenticationFinished),
286
));
287
288
case Routes.unlock:
282
- return MaterialPageRoute(
289
+ return MaterialPageRoute<void>(
290
fullscreenDialog: true,
291
builder: (_) => createUnlockPage(
292
sharedPreferences: sharedPreferences,
293
userService: userService,
294
walletService: walletService,
288
- onAuthenticationFinished: settings.arguments));
295
+ onAuthenticationFinished:
296
+ settings.arguments as OnAuthenticationFinished));
297
298
case Routes.nodeList:
291
- return CupertinoPageRoute(builder: (context) {
299
+ return CupertinoPageRoute<void>(builder: (context) {
300
return Provider(
301
create: (_) => NodeListStore(nodesSource: nodes),
302
child: NodeListPage());
303
});
304
305
case Routes.newNode:
298
- return CupertinoPageRoute(
306
+ return CupertinoPageRoute<void>(
307
builder: (_) => Provider<NodeListStore>(
308
create: (_) => NodeListStore(nodesSource: nodes),
309
child: NewNodePage()));
310
311
case Routes.login:
304
- return CupertinoPageRoute(builder: (context) {
312
+ return CupertinoPageRoute<void>(builder: (context) {
313
final authenticationStore = Provider.of<AuthenticationStore>(context);
314
315
return createLoginPage(
@@ -313,7 +321,7 @@ class Router {
321
});
322
323
case Routes.accountList:
316
- return MaterialPageRoute(
324
+ return MaterialPageRoute<void>(
325
builder: (context) {
326
return MultiProvider(providers: [
327
Provider(
@@ -324,14 +332,14 @@ class Router {
332
fullscreenDialog: true);
333
334
case Routes.accountCreation:
327
- return CupertinoPageRoute(builder: (context) {
335
+ return CupertinoPageRoute<String>(builder: (context) {
336
return Provider(
337
create: (_) => AccountListStore(walletService: walletService),
330
- child: AccountPage(account: settings.arguments));
338
+ child: AccountPage(account: settings.arguments as Account));
339
});
340
341
case Routes.addressBook:
334
- return MaterialPageRoute(builder: (context) {
342
+ return MaterialPageRoute<void>(builder: (context) {
343
return MultiProvider(
344
providers: [
345
Provider(
@@ -344,7 +352,7 @@ class Router {
352
});
353
354
case Routes.pickerAddressBook:
347
- return MaterialPageRoute(builder: (context) {
355
+ return MaterialPageRoute<void>(builder: (context) {
356
return MultiProvider(
357
providers: [
358
Provider(
@@ -357,7 +365,7 @@ class Router {
365
});
366
367
case Routes.addressBookAddContact:
360
- return CupertinoPageRoute(builder: (context) {
368
+ return CupertinoPageRoute<void>(builder: (context) {
369
return MultiProvider(
370
providers: [
371
Provider(
@@ -365,12 +373,12 @@ class Router {
373
AccountListStore(walletService: walletService)),
374
Provider(create: (_) => AddressBookStore(contacts: contacts))
375
],
368
- child: ContactPage(contact: settings.arguments),
376
+ child: ContactPage(contact: settings.arguments as Contact),
377
);
378
});
379
380
case Routes.showKeys:
373
- return MaterialPageRoute(
381
+ return MaterialPageRoute<void>(
382
builder: (context) {
383
return Provider(
384
create: (_) => WalletKeysStore(walletService: walletService),
@@ -380,12 +388,13 @@ class Router {
388
fullscreenDialog: true);
389
390
case Routes.exchangeTrade:
383
- return CupertinoPageRoute(
391
+ return CupertinoPageRoute<void>(
392
builder: (_) => MultiProvider(
393
providers: [
394
ProxyProvider<SettingsStore, ExchangeTradeStore>(
395
update: (_, settingsStore, __) => ExchangeTradeStore(
388
- trade: settings.arguments, walletStore: walletStore),
396
+ trade: settings.arguments as Trade,
397
+ walletStore: walletStore),
398
),
399
ProxyProvider<SettingsStore, SendStore>(
400
update: (_, settingsStore, __) => SendStore(
@@ -398,21 +407,22 @@ class Router {
407
));
408
409
case Routes.exchangeConfirm:
401
- return MaterialPageRoute(
402
- builder: (_) => ExchangeConfirmPage(trade: settings.arguments));
410
+ return MaterialPageRoute<void>(
411
+ builder: (_) =>
412
+ ExchangeConfirmPage(trade: settings.arguments as Trade));
413
414
case Routes.tradeDetails:
405
- return MaterialPageRoute(builder: (context) {
415
+ return MaterialPageRoute<void>(builder: (context) {
416
return MultiProvider(providers: [
417
ProxyProvider<SettingsStore, ExchangeTradeStore>(
418
update: (_, settingsStore, __) => ExchangeTradeStore(
409
- trade: settings.arguments, walletStore: walletStore),
419
+ trade: settings.arguments as Trade, walletStore: walletStore),
420
)
421
], child: TradeDetailsPage());
422
});
423
424
case Routes.subaddressList:
415
- return MaterialPageRoute(
425
+ return MaterialPageRoute<Subaddress>(
426
builder: (_) => MultiProvider(providers: [
427
Provider(
428
create: (_) =>
@@ -420,17 +430,18 @@ class Router {
430
], child: SubaddressListPage()));
431
432
case Routes.restoreWalletFromSeedDetails:
423
- return CupertinoPageRoute(
433
+ return CupertinoPageRoute<void>(
434
builder: (_) =>
435
ProxyProvider<AuthenticationStore, WalletRestorationStore>(
436
update: (_, authStore, __) => WalletRestorationStore(
437
authStore: authStore,
438
sharedPreferences: sharedPreferences,
439
walletListService: walletListService,
430
- seed: settings.arguments),
440
+ seed: settings.arguments as List<MnemoticItem>),
441
child: RestoreWalletFromSeedDetailsPage()));
442
+
443
case Routes.exchange:
433
- return MaterialPageRoute(
444
+ return MaterialPageRoute<void>(
445
builder: (_) => MultiProvider(providers: [
446
Provider(create: (_) {
447
final xmrtoprovider = XMRTOExchangeProvider();
@@ -449,25 +460,25 @@ class Router {
460
], child: ExchangePage()));
461
462
case Routes.settings:
452
- return MaterialPageRoute(
463
+ return MaterialPageRoute<void>(
464
builder: (_) => Provider(
465
create: (_) => NodeListStore(nodesSource: nodes),
466
child: SettingsPage()));
467
468
case Routes.rescan:
458
- return MaterialPageRoute(
469
+ return MaterialPageRoute<void>(
470
builder: (_) => Provider(
471
create: (_) => RescanWalletStore(walletService: walletService),
472
child: RescanPage()));
473
474
case Routes.faq:
464
- return MaterialPageRoute(builder: (_) => FaqPage());
475
+ return MaterialPageRoute<void>(builder: (_) => FaqPage());
476
477
case Routes.changeLanguage:
467
- return MaterialPageRoute(builder: (_) => ChangeLanguage());
478
+ return MaterialPageRoute<void>(builder: (_) => ChangeLanguage());
479
480
default:
470
- return MaterialPageRoute(
481
+ return MaterialPageRoute<void>(
482
builder: (_) => Scaffold(
483
body: Center(
484
child: Text(S.current.router_no_route(settings.name))),
lib/src/domain/common/balance_display_mode.dart
+3
-3
@@ -3,6 +3,9 @@ import 'package:cake_wallet/generated/i18n.dart';
3
import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
4
5
class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
6
+ const BalanceDisplayMode({@required String title, @required int raw})
7
+ : super(title: title, raw: raw);
8
+
9
static const all = [
10
BalanceDisplayMode.fullBalance,
11
BalanceDisplayMode.availableBalance,
@@ -27,9 +30,6 @@ class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
30
}
31
}
32
30
- const BalanceDisplayMode({@required String title, @required int raw})
31
- : super(title: title, raw: raw);
32
-
33
@override
34
String toString() {
35
switch (this) {
lib/src/domain/common/contact.dart
+4
-7
@@ -6,6 +6,9 @@ part 'contact.g.dart';
6
7
@HiveType()
8
class Contact extends HiveObject {
9
+ Contact({@required this.name, @required this.address, CryptoCurrency type})
10
+ : raw = type?.raw;
11
+
12
static const boxName = 'Contacts';
13
14
@HiveField(0)
@@ -19,12 +22,6 @@ class Contact extends HiveObject {
22
23
CryptoCurrency get type => CryptoCurrency.deserialize(raw: raw);
24
22
- Contact(
23
- {@required this.name,
24
- @required this.address,
25
- CryptoCurrency type})
26
- : raw = type?.raw;
27
-
28
- updateCryptoCurrency({@required CryptoCurrency currency}) =>
25
+ void updateCryptoCurrency({@required CryptoCurrency currency}) =>
26
raw = currency.raw;
27
}
lib/src/domain/common/crypto_currency.dart
+3
-3
@@ -5,6 +5,9 @@ part 'crypto_currency.g.dart';
5
6
@HiveType()
7
class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
8
+ const CryptoCurrency({final String title, final int raw})
9
+ : super(title: title, raw: raw);
10
+
11
static const all = [
12
CryptoCurrency.xmr,
13
CryptoCurrency.btc,
@@ -58,9 +61,6 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
61
}
62
}
63
61
- const CryptoCurrency({final String title, final int raw})
62
- : super(title: title, raw: raw);
63
-
64
@override
65
String toString() => title;
66
}
lib/src/domain/common/default_settings_migration.dart
+8
-8
@@ -11,7 +11,7 @@ Future defaultSettingsMigration(
11
{@required int version,
12
@required SharedPreferences sharedPreferences,
13
@required Box<Node> nodes}) async {
14
- int currentVersion =
14
+ final currentVersion =
15
sharedPreferences.getInt('current_default_settings_migration_version') ??
16
0;
17
@@ -22,17 +22,17 @@ Future defaultSettingsMigration(
22
try {
23
switch (version) {
24
case 1:
25
- sharedPreferences.setString(
25
+ await sharedPreferences.setString(
26
'current_fiat_currency', FiatCurrency.usd.toString());
27
- sharedPreferences.setInt(
27
+ await sharedPreferences.setInt(
28
'current_fee_priority', TransactionPriority.standart.raw);
29
- sharedPreferences.setInt('current_balance_display_mode',
29
+ await sharedPreferences.setInt('current_balance_display_mode',
30
BalanceDisplayMode.availableBalance.raw);
31
- sharedPreferences.setInt(
31
+ await sharedPreferences.setInt(
32
'current_default_settings_migration_version', 1);
33
- sharedPreferences.setBool('save_recipient_address', false);
33
+ await sharedPreferences.setBool('save_recipient_address', false);
34
await resetToDefault(nodes);
35
- sharedPreferences.setInt('current_node_id', 0);
35
+ await sharedPreferences.setInt('current_node_id', 0);
36
break;
37
default:
38
break;
@@ -41,6 +41,6 @@ Future defaultSettingsMigration(
41
print('Migration error: ${e.toString()}');
42
}
43
44
- sharedPreferences.setInt(
44
+ await sharedPreferences.setInt(
45
'current_default_settings_migration_version', version);
46
}
lib/src/domain/common/digest_request.dart
+27
-33
@@ -1,5 +1,5 @@
1
import 'dart:convert';
2
-import 'package:dio/dio.dart' as Dio;
2
+import 'package:dio/dio.dart' as __dio;
3
import 'package:crypto/crypto.dart' as crypto;
4
import 'dart:math' as math;
5
@@ -8,13 +8,13 @@ class DigestRequest {
8
9
String generateCnonce() {
10
final rnd = math.Random.secure();
11
- var values = List<int>.generate(32, (i) => rnd.nextInt(256));
11
+ final values = List<int>.generate(32, (i) => rnd.nextInt(256));
12
return base64Url.encode(values).substring(0, 8);
13
}
14
15
String generateHA1({String realm, String username, String password}) {
16
final ha1CredentialsData =
17
- Utf8Encoder().convert('$username:$realm:$password');
17
+ Utf8Encoder().convert('$username:$realm:$password');
18
final ha1 = md5.convert(ha1CredentialsData).toString();
19
20
return ha1;
@@ -29,13 +29,13 @@ class DigestRequest {
29
30
String generateResponseString(
31
{String ha1,
32
- String ha2,
33
- String nonce,
34
- String nonceCount,
35
- String cnonce,
36
- String qop}) {
32
+ String ha2,
33
+ String nonce,
34
+ String nonceCount,
35
+ String cnonce,
36
+ String qop}) {
37
final responseData =
38
- Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2');
38
+ Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2');
39
final response = md5.convert(responseData).toString();
40
41
return response;
@@ -43,8 +43,8 @@ class DigestRequest {
43
44
Map<String, String> parsetAuthorizationHeader({String source}) {
45
final authHeaderParts =
46
- source.substring(7).split(',').map((item) => item.trim());
47
- var authenticate = Map<String, String>();
46
+ source.substring(7).split(',').map((item) => item.trim());
47
+ final authenticate = Map<String, String>();
48
49
for (final part in authHeaderParts) {
50
final kv = part.split('=');
@@ -55,30 +55,25 @@ class DigestRequest {
55
return authenticate;
56
}
57
58
- Future<Dio.Response> request(
58
+ Future<__dio.Response> request(
59
{String uri, String login, String password}) async {
60
- final path = '/json_rpc';
61
- final method = 'POST';
60
+ const path = '/json_rpc';
61
+ const method = 'POST';
62
final url = Uri.http(uri, path);
63
- final dio = Dio.Dio();
64
-
65
- Map<String, String> headers = {'Content-type': 'application/json'};
66
- String body =
67
- json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"});
68
-
69
- var credentialsResponse = await dio.post(url.toString(),
70
- options: Dio.Options(headers: headers, validateStatus: (_) => true));
71
- var resHeaeders = credentialsResponse.headers;
72
- final authenticate =
73
- parsetAuthorizationHeader(source: resHeaeders['www-authenticate'].first);
63
+ final dio = __dio.Dio();
64
+ final headers = {'Content-type': 'application/json'};
65
+ final body =
66
+ json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"});
67
+ final credentialsResponse = await dio.post<Object>(url.toString(),
68
+ options: __dio.Options(headers: headers, validateStatus: (_) => true));
69
+ final authenticate = parsetAuthorizationHeader(
70
+ source: credentialsResponse.headers['www-authenticate'].first);
71
final qop = authenticate['qop'];
72
final algorithm = 'MD5';
73
final realm = 'monero-rpc';
74
final nonce = authenticate['nonce'];
75
final cnonce = generateCnonce();
79
-
80
- var nonceCount = '00000001';
81
-
76
+ final nonceCount = '00000001';
77
final ha1 = generateHA1(realm: realm, username: login, password: password);
78
final ha2 = generateHA2(method: method, uri: path);
79
final response = generateResponseString(
@@ -92,11 +87,10 @@ class DigestRequest {
87
final authorizationHeaders = {
88
'Content-type': 'application/json',
89
'Authorization':
95
- 'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"'
90
+ 'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"'
91
};
92
98
- final res = await dio.post(url.toString(),
99
- options: Dio.Options(headers: authorizationHeaders), data: body);
100
- return res;
93
+ return await dio.post<Object>(url.toString(),
94
+ options: __dio.Options(headers: authorizationHeaders), data: body);
95
}
102
-}
\ No newline at end of file
96
+}
lib/src/domain/common/enumerable_item.dart
+2
-2
@@ -1,11 +1,11 @@
1
import 'package:flutter/foundation.dart';
2
3
abstract class EnumerableItem<T> {
4
+ const EnumerableItem({@required this.title, @required this.raw});
5
+
6
final T raw;
7
final String title;
8
7
- const EnumerableItem({@required this.title, @required this.raw});
8
-
9
@override
10
String toString() => title;
11
}
lib/src/domain/common/fetch_price.dart
+3
-3
@@ -20,12 +20,12 @@ Future<double> fetchPriceFor({CryptoCurrency crypto, FiatCurrency fiat}) async {
20
return 0.0;
21
}
22
23
- final responseJSON = json.decode(response.body);
24
- final data = responseJSON['data'];
23
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
24
+ final data = responseJSON['data'] as List<Map<String, dynamic>>;
25
26
for (final item in data) {
27
if (item['symbol'] == cryptoToString(crypto)) {
28
- price = item['quote'][fiatStringified]['price'];
28
+ price = item['quote'][fiatStringified]['price'] as double;
29
break;
30
}
31
}
lib/src/domain/common/fiat_currency.dart
+5
-4
@@ -1,6 +1,11 @@
1
import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
2
3
class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
4
+ const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
5
+
6
+ @override
7
+ bool operator ==(Object other) => other is FiatCurrency && other.raw == raw;
8
+
9
static const all = [
10
FiatCurrency.aud,
11
FiatCurrency.bgn,
@@ -71,10 +76,6 @@ class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
76
static const zar = FiatCurrency(symbol: 'ZAR');
77
static const vef = FiatCurrency(symbol: 'VEF');
78
74
- const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
75
-
76
- operator ==(o) => o is FiatCurrency && o.raw == raw;
77
-
79
@override
80
int get hashCode => raw.hashCode ^ title.hashCode;
81
}
lib/src/domain/common/language.dart
+3
-5
@@ -1,16 +1,14 @@
1
import 'package:flutter/material.dart';
2
3
class Language with ChangeNotifier {
4
+ Language(this._currentLanguage);
5
6
String _currentLanguage;
7
7
- Language(this._currentLanguage);
8
-
9
- getCurrentLanguage() => _currentLanguage;
8
+ String getCurrentLanguage() => _currentLanguage;
9
11
- setCurrentLanguage(String language){
10
+ void setCurrentLanguage(String language) {
11
_currentLanguage = language;
12
notifyListeners();
13
}
15
-
14
}
\ No newline at end of file
lib/src/domain/common/mnemotic_item.dart
+3
-5
@@ -1,13 +1,11 @@
1
class MnemoticItem {
2
+ MnemoticItem({String text, this.dic}) : _text = text;
3
+
4
String get text => _text;
5
final List<String> dic;
6
7
String _text;
8
7
- MnemoticItem({String text, this.dic}) {
8
- _text = text;
9
- }
10
-
9
bool isCorrect() => dic.contains(text);
10
11
void changeText(String text) {
@@ -16,4 +14,4 @@ class MnemoticItem {
14
15
@override
16
String toString() => text;
19
-}
\ No newline at end of file
17
+}
lib/src/domain/common/node.dart
+15
-15
@@ -8,6 +8,13 @@ part 'node.g.dart';
8
9
@HiveType()
10
class Node extends HiveObject {
11
+ Node({@required this.uri, this.login, this.password});
12
+
13
+ Node.fromMap(Map map)
14
+ : uri = (map['uri'] ?? '') as String,
15
+ login = map['login'] as String,
16
+ password = map['password'] as String;
17
+
18
static const boxName = 'Nodes';
19
20
@HiveField(0)
@@ -19,31 +26,24 @@ class Node extends HiveObject {
26
@HiveField(2)
27
String password;
28
22
- Node({@required this.uri, this.login, this.password});
23
-
24
- Node.fromMap(Map map)
25
- : uri = map['uri'] ?? '',
26
- login = map['login'],
27
- password = map['password'];
28
-
29
Future<bool> requestNode(String uri, {String login, String password}) async {
30
- var resBody;
30
+ Map<String, dynamic> resBody;
31
32
if (login != null && password != null) {
33
final digestRequest = DigestRequest();
34
- var response = await digestRequest.request(
34
+ final response = await digestRequest.request(
35
uri: uri, login: login, password: password);
36
- resBody = response.data;
36
+ resBody = response.data as Map<String, dynamic>;
37
} else {
38
final url = Uri.http(uri, '/json_rpc');
39
- Map<String, String> headers = {'Content-type': 'application/json'};
40
- String body =
39
+ final headers = {'Content-type': 'application/json'};
40
+ final body =
41
json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"});
42
- var response =
42
+ final response =
43
await http.post(url.toString(), headers: headers, body: body);
44
- resBody = json.decode(response.body);
44
+ resBody = json.decode(response.body) as Map<String, dynamic>;
45
}
46
47
- return !resBody["result"]["offline"];
47
+ return !(resBody["result"]["offline"] as bool);
48
}
49
}
lib/src/domain/common/node_list.dart
+6
-5
@@ -4,20 +4,21 @@ import "package:yaml/yaml.dart";
4
import 'package:cake_wallet/src/domain/common/node.dart';
5
6
Future<List<Node>> loadDefaultNodes() async {
7
- String nodesRaw = await rootBundle.loadString('assets/node_list.yml');
8
- List nodes = loadYaml(nodesRaw);
7
+ final nodesRaw = await rootBundle.loadString('assets/node_list.yml');
8
+ final nodes = loadYaml(nodesRaw) as List<Map<dynamic, dynamic>>;
9
+
10
return nodes.map((raw) => Node.fromMap(raw)).toList();
11
}
12
13
Future resetToDefault(Box<Node> nodeSource) async {
14
final nodes = await loadDefaultNodes();
14
- await nodeSource.clear();
15
+ final enteties = Map<int, Node>();
16
16
- Map<int, Node> enteties = {};
17
+ await nodeSource.clear();
18
19
for (var i = 0; i < nodes.length; i++) {
20
enteties[i] = nodes[i];
21
}
22
23
await nodeSource.putAll(enteties);
23
-}
\ No newline at end of file
24
+}
lib/src/domain/common/pending_transaction.dart
+8
-8
@@ -1,15 +1,9 @@
1
import 'package:flutter/foundation.dart';
2
-import 'package:cw_monero/transaction_history.dart' as transactionHistory;
2
+import 'package:cw_monero/transaction_history.dart' as transaction_history;
3
import 'package:cw_monero/structs/pending_transaction.dart';
4
import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
5
6
class PendingTransaction {
7
- final String amount;
8
- final String fee;
9
- final String hash;
10
-
11
- int _pointerAddress;
12
-
7
PendingTransaction(
8
{@required this.amount, @required this.fee, @required this.hash});
9
@@ -20,6 +14,12 @@ class PendingTransaction {
14
hash = transactionDescription.hash,
15
_pointerAddress = transactionDescription.pointerAddress;
16
23
- Future commit() async => transactionHistory
17
+ final String amount;
18
+ final String fee;
19
+ final String hash;
20
+
21
+ int _pointerAddress;
22
+
23
+ Future<void> commit() async => transaction_history
24
.commitTransactionFromPointerAddress(address: _pointerAddress);
25
}
lib/src/domain/common/qr_scanner.dart
+1
-1
@@ -10,6 +10,6 @@ Future<String> presentQRScanner() async {
10
return result;
11
} catch (e) {
12
isQrScannerShown = false;
13
- throw e;
13
+ rethrow;
14
}
15
}
lib/src/domain/common/sync_status.dart
+17
-3
@@ -9,18 +9,20 @@ abstract class SyncStatus {
9
}
10
11
class SyncingSyncStatus extends SyncStatus {
12
+ SyncingSyncStatus(this.height, this.blockchainHeight, this.refreshHeight);
13
+
14
final int height;
15
final int blockchainHeight;
16
final int refreshHeight;
17
16
- SyncingSyncStatus(this.height, this.blockchainHeight, this.refreshHeight);
17
-
18
+ @override
19
double progress() {
20
final line = blockchainHeight - refreshHeight;
21
final diff = line - (blockchainHeight - height);
22
return diff <= 0 ? 0.0 : diff / line;
23
}
24
25
+ @override
26
String title() => S.current.sync_status_syncronizing;
27
28
@override
@@ -28,39 +30,51 @@ class SyncingSyncStatus extends SyncStatus {
30
}
31
32
class SyncedSyncStatus extends SyncStatus {
33
+ @override
34
double progress() => 1.0;
35
36
+ @override
37
String title() => S.current.sync_status_syncronized;
38
}
39
40
class NotConnectedSyncStatus extends SyncStatus {
41
const NotConnectedSyncStatus();
42
43
+ @override
44
double progress() => 0.0;
45
46
+ @override
47
String title() => S.current.sync_status_not_connected;
48
}
49
50
class StartingSyncStatus extends SyncStatus {
51
+ @override
52
double progress() => 0.0;
53
54
+ @override
55
String title() => S.current.sync_status_starting_sync;
56
}
57
58
class FailedSyncStatus extends SyncStatus {
59
+ @override
60
double progress() => 1.0;
61
62
+ @override
63
String title() => S.current.sync_status_failed_connect;
64
}
65
66
class ConnectingSyncStatus extends SyncStatus {
67
+ @override
68
double progress() => 0.0;
69
70
+ @override
71
String title() => S.current.sync_status_connecting;
72
}
73
74
class ConnectedSyncStatus extends SyncStatus {
75
+ @override
76
double progress() => 0.0;
77
78
+ @override
79
String title() => S.current.sync_status_connected;
66
-}
\ No newline at end of file
80
+}
lib/src/domain/common/transaction_info.dart
+22
-20
@@ -4,26 +4,20 @@ import 'package:cake_wallet/src/domain/common/parseBoolFromString.dart';
4
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
5
6
class TransactionInfo {
7
- final String id;
8
- final int height;
9
- final TransactionDirection direction;
10
- final DateTime date;
11
- final int accountIndex;
12
- final bool isPending;
13
- final int amount;
14
- String recipientAddress;
15
- String _fiatAmount;
7
+ TransactionInfo(this.id, this.height, this.direction, this.date,
8
+ this.isPending, this.amount, this.accountIndex);
9
10
TransactionInfo.fromMap(Map map)
18
- : id = map['hash'] ?? '',
19
- height = map['height'] ?? '',
20
- direction = parseTransactionDirectionFromNumber(map['direction']) ??
21
- TransactionDirection.incoming,
11
+ : id = (map['hash'] ?? '') as String,
12
+ height = (map['height'] ?? 0) as int,
13
+ direction =
14
+ parseTransactionDirectionFromNumber(map['direction'] as String) ??
15
+ TransactionDirection.incoming,
16
date = DateTime.fromMillisecondsSinceEpoch(
23
- (int.parse(map['timestamp']) ?? 0) * 1000),
24
- isPending = parseBoolFromString(map['isPending']),
25
- amount = map['amount'],
26
- accountIndex = int.parse(map['accountIndex']);
17
+ (int.parse(map['timestamp'] as String) ?? 0) * 1000),
18
+ isPending = parseBoolFromString(map['isPending'] as String),
19
+ amount = map['amount'] as int,
20
+ accountIndex = int.parse(map['accountIndex'] as String);
21
22
TransactionInfo.fromRow(TransactionInfoRow row)
23
: id = row.getHash(),
@@ -35,12 +29,20 @@ class TransactionInfo {
29
amount = row.getAmount(),
30
accountIndex = row.subaddrAccount;
31
38
- TransactionInfo(this.id, this.height, this.direction, this.date,
39
- this.isPending, this.amount, this.accountIndex);
32
+ final String id;
33
+ final int height;
34
+ final TransactionDirection direction;
35
+ final DateTime date;
36
+ final int accountIndex;
37
+ final bool isPending;
38
+ final int amount;
39
+ String recipientAddress;
40
+
41
+ String _fiatAmount;
42
43
String amountFormatted() => '${moneroAmountToString(amount: amount)} XMR';
44
45
String fiatAmount() => _fiatAmount ?? '';
46
45
- changeFiatAmount(String amount) => _fiatAmount = amount;
47
+ void changeFiatAmount(String amount) => _fiatAmount = amount;
48
}
lib/src/domain/common/transaction_priority.dart
+3
-3
@@ -2,6 +2,9 @@ import 'package:cake_wallet/generated/i18n.dart';
2
import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
3
4
class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
5
+ const TransactionPriority({String title, int raw})
6
+ : super(title: title, raw: raw);
7
+
8
static const all = [
9
TransactionPriority.slow,
10
TransactionPriority.regular,
@@ -33,9 +36,6 @@ class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
36
}
37
}
38
36
- const TransactionPriority({String title, int raw})
37
- : super(title: title, raw: raw);
38
-
39
@override
40
String toString() {
41
switch (this) {
lib/src/domain/common/wallet_description.dart
+2
-2
@@ -1,8 +1,8 @@
1
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
2
3
class WalletDescription {
4
+ WalletDescription({this.name, this.type});
5
+
6
final String name;
7
final WalletType type;
6
-
7
- WalletDescription({this.name, this.type});
8
}
\ No newline at end of file
lib/src/domain/common/wallet_info.dart
+4
-4
@@ -5,8 +5,11 @@ part 'wallet_info.g.dart';
5
6
@HiveType()
7
class WalletInfo extends HiveObject {
8
+ WalletInfo(
9
+ {this.id, this.name, this.type, this.isRecovery, this.restoreHeight});
10
+
11
static const boxName = 'WalletInfo';
9
-
12
+
13
@HiveField(0)
14
String id;
15
@@ -21,7 +24,4 @@ class WalletInfo extends HiveObject {
24
25
@HiveField(4)
26
int restoreHeight;
24
-
25
- WalletInfo(
26
- {this.id, this.name, this.type, this.isRecovery, this.restoreHeight});
27
}
lib/src/domain/exchange/changenow/changenow_exchange_provider.dart
+65
-41
@@ -15,45 +15,50 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da
15
import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart';
16
17
class ChangeNowExchangeProvider extends ExchangeProvider {
18
+ ChangeNowExchangeProvider()
19
+ : super(
20
+ pairList: CryptoCurrency.all
21
+ .map((i) {
22
+ return CryptoCurrency.all.map((k) {
23
+ if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) {
24
+ return ExchangePair(from: i, to: k, reverse: false);
25
+ }
26
+
27
+ if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) {
28
+ return null;
29
+ }
30
+
31
+ return ExchangePair(from: i, to: k, reverse: true);
32
+ }).where((c) => c != null);
33
+ })
34
+ .expand((i) => i)
35
+ .toList());
36
+
37
static const apiUri = 'https://changenow.io/api/v1';
38
static const apiKey = secrets.change_now_api_key;
39
static const _exchangeAmountUriSufix = '/exchange-amount/';
40
static const _transactionsUriSufix = '/transactions/';
41
static const _minAmountUriSufix = '/min-amount/';
42
43
+ @override
44
String get title => 'ChangeNOW';
45
+
46
+ @override
47
ExchangeProviderDescription get description =>
48
ExchangeProviderDescription.changeNow;
49
28
- ChangeNowExchangeProvider() {
29
- pairList = CryptoCurrency.all
30
- .map((i) {
31
- return CryptoCurrency.all.map((k) {
32
- if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) {
33
- return ExchangePair(from: i, to: k, reverse: false);
34
- }
35
-
36
- if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) {
37
- return null;
38
- }
39
-
40
- return ExchangePair(from: i, to: k, reverse: true);
41
- }).where((c) => c != null);
42
- })
43
- .expand((i) => i)
44
- .toList();
45
- }
46
-
50
+ @override
51
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
52
final symbol = from.toString() + '_' + to.toString();
53
final url = apiUri + _minAmountUriSufix + symbol;
54
final response = await get(url);
51
- final responseJSON = json.decode(response.body);
52
- final double min = responseJSON['minAmount'];
55
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
56
+ final min = responseJSON['minAmount'] as double;
57
58
return Limits(min: min, max: null);
59
}
60
61
+ @override
62
Future<Trade> createTrade({TradeRequest request}) async {
63
const url = apiUri + _transactionsUriSufix + apiKey;
64
final _request = request as ChangeNowRequest;
@@ -70,37 +75,44 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
75
76
if (response.statusCode != 200) {
77
if (response.statusCode == 400) {
73
- final responseJSON = json.decode(response.body);
74
- final error = responseJSON['message'];
78
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
79
+ final error = responseJSON['message'] as String;
80
+
81
throw TradeNotCreatedException(description, description: error);
82
}
83
84
throw TradeNotCreatedException(description);
85
}
86
81
- final responseJSON = json.decode(response.body);
87
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
88
+ final id = responseJSON['id'] as String;
89
+ final inputAddress = responseJSON['payinAddress'] as String;
90
+ final refundAddress = responseJSON['refundAddress'] as String;
91
+ final extraId = responseJSON['payinExtraId'] as String;
92
93
return Trade(
84
- id: responseJSON['id'],
94
+ id: id,
95
from: _request.from,
96
to: _request.to,
97
provider: description,
88
- inputAddress: responseJSON['payinAddress'],
89
- refundAddress: responseJSON['refundAddress'],
90
- extraId: responseJSON["payinExtraId"],
98
+ inputAddress: inputAddress,
99
+ refundAddress: refundAddress,
100
+ extraId: extraId,
101
createdAt: DateTime.now(),
102
amount: _request.amount,
103
state: TradeState.created);
104
}
105
106
+ @override
107
Future<Trade> findTradeById({@required String id}) async {
108
final url = apiUri + _transactionsUriSufix + id + '/' + apiKey;
109
final response = await get(url);
110
111
if (response.statusCode != 200) {
112
if (response.statusCode == 400) {
102
- final responseJSON = json.decode(response.body);
103
- final error = responseJSON['message'];
113
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
114
+ final error = responseJSON['message'] as String;
115
+
116
throw TradeNotFoundException(id,
117
provider: description, description: error);
118
}
@@ -108,20 +120,31 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
120
throw TradeNotFoundException(id, provider: description);
121
}
122
111
- final responseJSON = json.decode(response.body);
112
-
123
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
124
+ final fromCurrency = responseJSON['fromCurrency'] as String;
125
+ final from = CryptoCurrency.fromString(fromCurrency);
126
+ final toCurrency = responseJSON['toCurrency'] as String;
127
+ final to = CryptoCurrency.fromString(toCurrency);
128
+ final inputAddress = responseJSON['payinAddress'] as String;
129
+ final expectedSendAmount = responseJSON['expectedSendAmount'].toString();
130
+ final status = responseJSON['status'] as String;
131
+ final state = TradeState.deserialize(raw: status);
132
+ final extraId = responseJSON['payinExtraId'] as String;
133
+ final outputTransaction = responseJSON['payoutHash'] as String;
134
+
135
return Trade(
136
id: id,
115
- from: CryptoCurrency.fromString(responseJSON['fromCurrency']),
116
- to: CryptoCurrency.fromString(responseJSON['toCurrency']),
137
+ from: from,
138
+ to: to,
139
provider: description,
118
- inputAddress: responseJSON['payinAddress'],
119
- amount: responseJSON['expectedSendAmount'].toString(),
120
- state: TradeState.deserialize(raw: responseJSON['status']),
121
- extraId: responseJSON['payinExtraId'],
122
- outputTransaction: responseJSON['payoutHash']);
140
+ inputAddress: inputAddress,
141
+ amount: expectedSendAmount,
142
+ state: state,
143
+ extraId: extraId,
144
+ outputTransaction: outputTransaction);
145
}
146
147
+ @override
148
Future<double> calculateAmount(
149
{CryptoCurrency from, CryptoCurrency to, double amount}) async {
150
final url = apiUri +
@@ -132,8 +155,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
155
'_' +
156
to.toString();
157
final response = await get(url);
135
- final responseJSON = json.decode(response.body);
158
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
159
+ final estimatedAmount = responseJSON['estimatedAmount'] as double;
160
137
- return responseJSON['estimatedAmount'];
161
+ return estimatedAmount;
162
}
163
}
lib/src/domain/exchange/changenow/changenow_request.dart
+6
-6
@@ -3,16 +3,16 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3
import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
4
5
class ChangeNowRequest extends TradeRequest {
6
- CryptoCurrency from;
7
- CryptoCurrency to;
8
- String address;
9
- String amount;
10
- String refundAddress;
11
-
6
ChangeNowRequest(
7
{@required this.from,
8
@required this.to,
9
@required this.address,
10
@required this.amount,
11
@required this.refundAddress});
12
+
13
+ CryptoCurrency from;
14
+ CryptoCurrency to;
15
+ String address;
16
+ String amount;
17
+ String refundAddress;
18
}
lib/src/domain/exchange/exchange_pair.dart
+3
-3
@@ -1,9 +1,9 @@
1
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
2
3
class ExchangePair {
4
+ ExchangePair({this.from, this.to, this.reverse = true});
5
+
6
final CryptoCurrency from;
7
final CryptoCurrency to;
8
final bool reverse;
7
-
8
- ExchangePair({this.from, this.to, this.reverse = true});
9
-}
\ No newline at end of file
9
+}
lib/src/domain/exchange/exchange_provider.dart
+2
@@ -7,6 +7,8 @@ import 'package:cake_wallet/src/domain/exchange/trade.dart';
7
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
8
9
abstract class ExchangeProvider {
10
+ ExchangeProvider({this.pairList});
11
+
12
String get title;
13
List<ExchangePair> pairList;
14
ExchangeProviderDescription description;
lib/src/domain/exchange/exchange_provider_description.dart
+3
-5
@@ -2,6 +2,9 @@ import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
2
3
class ExchangeProviderDescription extends EnumerableItem<int>
4
with Serializable<int> {
5
+ const ExchangeProviderDescription({String title, int raw})
6
+ : super(title: title, raw: raw);
7
+
8
static const xmrto = ExchangeProviderDescription(title: 'XMR.TO', raw: 0);
9
static const changeNow =
10
ExchangeProviderDescription(title: 'ChangeNOW', raw: 1);
@@ -16,9 +19,4 @@ class ExchangeProviderDescription extends EnumerableItem<int>
19
return null;
20
}
21
}
19
-
20
- final String title;
21
-
22
- const ExchangeProviderDescription({this.title, int raw})
23
- : super(title: title, raw: raw);
22
}
lib/src/domain/exchange/limits.dart
+2
-2
@@ -1,6 +1,6 @@
1
class Limits {
2
+ const Limits({this.min, this.max});
3
+
4
final double min;
5
final double max;
4
-
5
- const Limits({this.min, this.max});
6
}
\ No newline at end of file
lib/src/domain/exchange/trade.dart
+28
-27
@@ -7,6 +7,25 @@ part 'trade.g.dart';
7
8
@HiveType()
9
class Trade extends HiveObject {
10
+ Trade(
11
+ {this.id,
12
+ ExchangeProviderDescription provider,
13
+ CryptoCurrency from,
14
+ CryptoCurrency to,
15
+ TradeState state,
16
+ this.createdAt,
17
+ this.expiredAt,
18
+ this.amount,
19
+ this.inputAddress,
20
+ this.extraId,
21
+ this.outputTransaction,
22
+ this.refundAddress,
23
+ this.walletId})
24
+ : providerRaw = provider?.raw,
25
+ fromRaw = from?.raw,
26
+ toRaw = to?.raw,
27
+ stateRaw = state?.raw;
28
+
29
static const boxName = 'Trades';
30
31
@HiveField(0)
@@ -59,38 +78,20 @@ class Trade extends HiveObject {
78
79
static Trade fromMap(Map map) {
80
return Trade(
62
- id: map['id'],
63
- provider: ExchangeProviderDescription.deserialize(raw: map['provider']),
64
- from: CryptoCurrency.deserialize(raw: map['input']),
65
- to: CryptoCurrency.deserialize(raw: map['output']),
81
+ id: map['id'] as String,
82
+ provider: ExchangeProviderDescription.deserialize(
83
+ raw: map['provider'] as int),
84
+ from: CryptoCurrency.deserialize(raw: map['input'] as int),
85
+ to: CryptoCurrency.deserialize(raw: map['output'] as int),
86
createdAt: map['date'] != null
67
- ? DateTime.fromMillisecondsSinceEpoch(map['date'])
87
+ ? DateTime.fromMillisecondsSinceEpoch(map['date'] as int)
88
: null,
69
- amount: map['amount'],
70
- walletId: map['wallet_id']);
89
+ amount: map['amount'] as String,
90
+ walletId: map['wallet_id'] as String);
91
}
92
73
- Trade(
74
- {this.id,
75
- ExchangeProviderDescription provider,
76
- CryptoCurrency from,
77
- CryptoCurrency to,
78
- TradeState state,
79
- this.createdAt,
80
- this.expiredAt,
81
- this.amount,
82
- this.inputAddress,
83
- this.extraId,
84
- this.outputTransaction,
85
- this.refundAddress,
86
- this.walletId})
87
- : providerRaw = provider?.raw,
88
- fromRaw = from?.raw,
89
- toRaw = to?.raw,
90
- stateRaw = state?.raw;
91
-
93
Map<String, dynamic> toMap() {
93
- return {
94
+ return <String, dynamic>{
95
'id': id,
96
'provider': provider.serialize(),
97
'input': from.serialize(),
lib/src/domain/exchange/trade_not_created_exeption.dart
+2
-2
@@ -2,11 +2,11 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da
2
import 'package:cake_wallet/generated/i18n.dart';
3
4
class TradeNotCreatedException implements Exception {
5
+ TradeNotCreatedException(this.provider, {this.description = ''});
6
+
7
ExchangeProviderDescription provider;
8
String description;
9
8
- TradeNotCreatedException(this.provider, {this.description = ''});
9
-
10
@override
11
String toString() {
12
var text = provider != null
lib/src/domain/exchange/trade_not_found_exeption.dart
+2
-2
@@ -2,12 +2,12 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da
2
import 'package:cake_wallet/generated/i18n.dart';
3
4
class TradeNotFoundException implements Exception {
5
+ TradeNotFoundException(this.tradeId, {this.provider, this.description = ''});
6
+
7
String tradeId;
8
ExchangeProviderDescription provider;
9
String description;
10
9
- TradeNotFoundException(this.tradeId, {this.provider, this.description = ''});
10
-
11
@override
12
String toString() {
13
var text = tradeId != null && provider != null
lib/src/domain/exchange/trade_state.dart
+6
-5
@@ -2,6 +2,12 @@ import 'package:flutter/foundation.dart';
2
import 'package:cake_wallet/src/domain/common/enumerable_item.dart';
3
4
class TradeState extends EnumerableItem<String> with Serializable<String> {
5
+ const TradeState({@required String raw, @required String title})
6
+ : super(raw: raw, title: title);
7
+
8
+ @override
9
+ bool operator ==(Object other) => other is TradeState && other.raw == raw;
10
+
11
static const pending = TradeState(raw: 'pending', title: 'Pending');
12
static const confirming = TradeState(raw: 'confirming', title: 'Confirming');
13
static const trading = TradeState(raw: 'trading', title: 'Trading');
@@ -58,11 +64,6 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
64
}
65
}
66
61
- const TradeState({@required String raw, @required String title})
62
- : super(raw: raw, title: title);
63
-
64
- operator ==(o) => o is TradeState && o.raw == raw;
65
-
67
@override
68
int get hashCode => raw.hashCode ^ title.hashCode;
69
}
lib/src/domain/exchange/xmrto/xmrto_exchange_provider.dart
+34
-24
@@ -14,6 +14,12 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da
14
import 'package:cake_wallet/src/domain/exchange/trade_not_found_exeption.dart';
15
16
class XMRTOExchangeProvider extends ExchangeProvider {
17
+ XMRTOExchangeProvider()
18
+ : super(pairList: [
19
+ ExchangePair(
20
+ from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false)
21
+ ]);
22
+
23
static const userAgent = 'CakeWallet/XMR iOS';
24
static const originalApiUri = 'https://xmr.to/api/v2/xmr2btc';
25
static const proxyApiUri = 'https://xmrproxy.net/api/v2/xmr2btc';
@@ -35,18 +41,16 @@ class XMRTOExchangeProvider extends ExchangeProvider {
41
return _apiUri;
42
}
43
44
+ @override
45
String get title => 'XMR.TO';
46
47
+ @override
48
ExchangeProviderDescription get description =>
49
ExchangeProviderDescription.xmrto;
50
43
- List<ExchangePair> pairList = [
44
- ExchangePair(
45
- from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false)
46
- ];
47
-
51
double _rate = 0;
52
53
+ @override
54
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
55
final url = await getApiUri() + _orderParameterUriSufix;
56
final response = await get(url);
@@ -55,13 +59,14 @@ class XMRTOExchangeProvider extends ExchangeProvider {
59
return Limits(min: 0, max: 0);
60
}
61
58
- final responseJSON = json.decode(response.body);
59
- final double min = responseJSON['lower_limit'];
60
- final double max = responseJSON['upper_limit'];
62
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
63
+ final min = responseJSON['lower_limit'] as double;
64
+ final max = responseJSON['upper_limit'] as double;
65
66
return Limits(min: min, max: max);
67
}
68
69
+ @override
70
Future<Trade> createTrade({TradeRequest request}) async {
71
final _request = request as XMRTOTradeRequest;
72
final url = await getApiUri() + _orderCreateUriSufix;
@@ -74,16 +79,17 @@ class XMRTOExchangeProvider extends ExchangeProvider {
79
80
if (response.statusCode != 201) {
81
if (response.statusCode == 400) {
77
- final responseJSON = json.decode(response.body);
78
- throw TradeNotCreatedException(description,
79
- description: responseJSON['error_msg']);
82
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
83
+ final error = responseJSON['error_msg'] as String;
84
+
85
+ throw TradeNotCreatedException(description, description: error);
86
}
87
88
throw TradeNotCreatedException(description);
89
}
90
85
- final responseJSON = json.decode(response.body);
86
- final uuid = responseJSON["uuid"];
91
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
92
+ final uuid = responseJSON["uuid"] as String;
93
94
return Trade(
95
id: uuid,
@@ -95,6 +101,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
101
createdAt: DateTime.now());
102
}
103
104
+ @override
105
Future<Trade> findTradeById({@required String id}) async {
106
const headers = {
107
'Content-Type': 'application/json',
@@ -106,8 +113,9 @@ class XMRTOExchangeProvider extends ExchangeProvider {
113
114
if (response.statusCode != 200) {
115
if (response.statusCode == 400) {
109
- final responseJSON = json.decode(response.body);
110
- final error = responseJSON['error_msg'];
116
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
117
+ final error = responseJSON['error_msg'] as String;
118
+
119
throw TradeNotFoundException(id,
120
provider: description, description: error);
121
}
@@ -115,14 +123,14 @@ class XMRTOExchangeProvider extends ExchangeProvider {
123
throw TradeNotFoundException(id, provider: description);
124
}
125
118
- final responseJSON = json.decode(response.body);
119
- final address = responseJSON['xmr_receiving_integrated_address'];
120
- final paymentId = responseJSON['xmr_required_payment_id_short'];
126
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
127
+ final address = responseJSON['xmr_receiving_integrated_address'] as String;
128
+ final paymentId = responseJSON['xmr_required_payment_id_short'] as String;
129
final amount = responseJSON['xmr_amount_total'].toString();
122
- final stateRaw = responseJSON['state'];
123
- final expiredAtRaw = responseJSON['expires_at'];
130
+ final stateRaw = responseJSON['state'] as String;
131
+ final expiredAtRaw = responseJSON['expires_at'] as String;
132
final expiredAt = DateTime.parse(expiredAtRaw).toLocal();
125
- final outputTransaction = responseJSON['btc_transaction_id'];
133
+ final outputTransaction = responseJSON['btc_transaction_id'] as String;
134
final state = TradeState.deserialize(raw: stateRaw);
135
136
return Trade(
@@ -138,6 +146,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
146
outputTransaction: outputTransaction);
147
}
148
149
+ @override
150
Future<double> calculateAmount(
151
{CryptoCurrency from, CryptoCurrency to, double amount}) async {
152
if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) {
@@ -158,9 +167,10 @@ class XMRTOExchangeProvider extends ExchangeProvider {
167
final url = await getApiUri() + _orderParameterUriSufix;
168
final response =
169
await get(url, headers: {'Content-Type': 'application/json'});
161
- final responseJSON = json.decode(response.body);
162
- double btcprice = responseJSON['price'];
163
- double price = 1 / btcprice;
170
+ final responseJSON = json.decode(response.body) as Map<String, dynamic>;
171
+ final btcprice = responseJSON['price'] as double;
172
+ final price = 1 / btcprice;
173
+
174
return price;
175
} catch (e) {
176
print(e.toString());
lib/src/domain/exchange/xmrto/xmrto_trade_request.dart
+6
-6
@@ -3,16 +3,16 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3
import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
4
5
class XMRTOTradeRequest extends TradeRequest {
6
- final CryptoCurrency from;
7
- final CryptoCurrency to;
8
- final String amount;
9
- final String address;
10
- final String refundAddress;
11
-
6
XMRTOTradeRequest(
7
{@required this.from,
8
@required this.to,
9
@required this.amount,
10
@required this.address,
11
@required this.refundAddress});
12
+
13
+ final CryptoCurrency from;
14
+ final CryptoCurrency to;
15
+ final String amount;
16
+ final String address;
17
+ final String refundAddress;
18
}
lib/src/domain/monero/account.dart
+5
-5
@@ -1,16 +1,16 @@
1
import 'package:cw_monero/structs/account_row.dart';
2
3
class Account {
4
- final int id;
5
- final String label;
6
-
4
Account({this.id, this.label});
5
6
Account.fromMap(Map map)
10
- : this.id = map['id'] == null ? 0 : int.parse(map['id']),
11
- this.label = map['label'] ?? '';
7
+ : this.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
8
+ this.label = (map['label'] ?? '') as String;
9
10
Account.fromRow(AccountRow row)
11
: this.id = row.getId(),
12
this.label = row.getLabel();
13
+
14
+ final int id;
15
+ final String label;
16
}
lib/src/domain/monero/account_list.dart
+16
-15
@@ -1,20 +1,20 @@
1
import 'package:rxdart/rxdart.dart';
2
-import 'package:cw_monero/account_list.dart' as accountListAPI;
2
+import 'package:cw_monero/account_list.dart' as account_list;
3
import 'package:cake_wallet/src/domain/monero/account.dart';
4
5
class AccountList {
6
- get accounts => _accounts.stream;
7
- BehaviorSubject<List<Account>> _accounts;
8
-
9
- bool _isRefreshing;
10
- bool _isUpdating;
11
-
6
AccountList() {
7
_isRefreshing = false;
8
_isUpdating = false;
9
_accounts = BehaviorSubject<List<Account>>();
10
}
11
12
+ Observable<List<Account>> get accounts => _accounts.stream;
13
+
14
+ BehaviorSubject<List<Account>> _accounts;
15
+ bool _isRefreshing;
16
+ bool _isUpdating;
17
+
18
Future update() async {
19
if (_isUpdating) {
20
return;
@@ -22,46 +22,47 @@ class AccountList {
22
23
try {
24
_isUpdating = true;
25
- await refresh();
25
+ refresh();
26
final accounts = getAll();
27
_accounts.add(accounts);
28
_isUpdating = false;
29
} catch (e) {
30
_isUpdating = false;
31
- throw e;
31
+ rethrow;
32
}
33
}
34
35
List<Account> getAll() {
36
- return accountListAPI
36
+ return account_list
37
.getAllAccount()
38
.map((accountRow) => Account.fromRow(accountRow))
39
.toList();
40
}
41
42
Future addAccount({String label}) async {
43
- await accountListAPI.addAccount(label: label);
43
+ await account_list.addAccount(label: label);
44
await update();
45
}
46
47
Future setLabelSubaddress({int accountIndex, String label}) async {
48
- await accountListAPI.setLabelForAccount(accountIndex: accountIndex, label: label);
48
+ await account_list.setLabelForAccount(
49
+ accountIndex: accountIndex, label: label);
50
await update();
51
}
52
52
- refresh() {
53
+ void refresh() {
54
if (_isRefreshing) {
55
return;
56
}
57
58
try {
59
_isRefreshing = true;
59
- accountListAPI.refreshAccounts();
60
+ account_list.refreshAccounts();
61
_isRefreshing = false;
62
} catch (e) {
63
_isRefreshing = false;
64
print(e);
64
- throw e;
65
+ rethrow;
66
}
67
}
68
}
lib/src/domain/monero/get_height_by_date.dart
+8
-7
@@ -77,7 +77,8 @@ int getHeigthByDate({DateTime date}) {
77
78
if (endHeight <= 0) {
79
endHeight = dates.values.toList()[dates.length - 1];
80
- final preLastDate = dateFormat.parse(dates.keys.elementAt(dates.keys.length - 2));
80
+ final preLastDate =
81
+ dateFormat.parse(dates.keys.elementAt(dates.keys.length - 2));
82
preLastYear = preLastDate.year;
83
preLastMonth = preLastDate.month;
84
} else {
@@ -90,12 +91,12 @@ int getHeigthByDate({DateTime date}) {
91
preLastYear -= 1;
92
}
93
93
- var startRaw = '$preLastYear' + '-' + '$preLastMonth';
94
- var startHeight = dates[startRaw];
95
- var diff = endHeight - startHeight;
96
- var heightPerDay = diff / 30;
97
- var daysHeight = date.day * heightPerDay.round();
98
- var height = endHeight + daysHeight;
94
+ final startRaw = '$preLastYear' + '-' + '$preLastMonth';
95
+ final startHeight = dates[startRaw];
96
+ final diff = endHeight - startHeight;
97
+ final heightPerDay = diff / 30;
98
+ final daysHeight = date.day * heightPerDay.round();
99
+ final height = endHeight + daysHeight;
100
101
return height;
102
}
lib/src/domain/monero/monero_balance.dart
+2
-2
@@ -2,8 +2,8 @@ import 'package:flutter/foundation.dart';
2
import 'package:cake_wallet/src/domain/common/balance.dart';
3
4
class MoneroBalance extends Balance {
5
+ MoneroBalance({@required this.fullBalance, @required this.unlockedBalance});
6
+
7
final String fullBalance;
8
final String unlockedBalance;
7
-
8
- MoneroBalance({@required this.fullBalance, @required this.unlockedBalance});
9
}
lib/src/domain/monero/monero_transaction_creation_credentials.dart
+4
-4
@@ -3,11 +3,11 @@ import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
3
4
class MoneroTransactionCreationCredentials
5
extends TransactionCreationCredentials {
6
+ MoneroTransactionCreationCredentials(
7
+ {this.address, this.paymentId, this.priority, this.amount});
8
+
9
final String address;
10
final String paymentId;
11
final String amount;
12
final TransactionPriority priority;
10
-
11
- MoneroTransactionCreationCredentials(
12
- {this.address, this.paymentId, this.priority, this.amount});
13
-}
\ No newline at end of file
13
+}
lib/src/domain/monero/monero_transaction_history.dart
+17
-11
@@ -1,26 +1,29 @@
1
import 'dart:core';
2
import 'package:flutter/services.dart';
3
import 'package:rxdart/rxdart.dart';
4
-import 'package:cw_monero/transaction_history.dart' as moneroTransactionHistory;
4
+import 'package:cw_monero/transaction_history.dart'
5
+ as monero_transaction_history;
6
import 'package:cake_wallet/src/domain/common/transaction_history.dart';
7
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
8
8
-List<TransactionInfo> _getAllTransactions(_) => moneroTransactionHistory
9
+List<TransactionInfo> _getAllTransactions(dynamic _) => monero_transaction_history
10
.getAllTransations()
11
.map((row) => TransactionInfo.fromRow(row))
12
.toList();
13
14
class MoneroTransactionHistory extends TransactionHistory {
14
- get transactions => _transactions.stream;
15
- BehaviorSubject<List<TransactionInfo>> _transactions;
15
+ MoneroTransactionHistory()
16
+ : _transactions = BehaviorSubject<List<TransactionInfo>>.seeded([]);
17
+
18
+ @override
19
+ Observable<List<TransactionInfo>> get transactions => _transactions.stream;
20
21
+ final BehaviorSubject<List<TransactionInfo>> _transactions;
22
bool _isUpdating = false;
23
bool _isRefreshing = false;
24
bool _needToCheckForRefresh = false;
25
21
- MoneroTransactionHistory()
22
- : _transactions = BehaviorSubject<List<TransactionInfo>>.seeded([]);
23
-
26
+ @override
27
Future update() async {
28
if (_isUpdating) {
29
return;
@@ -38,15 +41,18 @@ class MoneroTransactionHistory extends TransactionHistory {
41
} catch (e) {
42
_isUpdating = false;
43
print(e);
41
- throw e;
44
+ rethrow;
45
}
46
}
47
48
+ @override
49
Future<List<TransactionInfo>> getAll({bool force = false}) async =>
50
_getAllTransactions(null);
51
48
- Future<int> count() async => moneroTransactionHistory.countOfTransactions();
52
+ @override
53
+ Future<int> count() async => monero_transaction_history.countOfTransactions();
54
55
+ @override
56
Future refresh() async {
57
if (_isRefreshing) {
58
return;
@@ -54,12 +60,12 @@ class MoneroTransactionHistory extends TransactionHistory {
60
61
try {
62
_isRefreshing = true;
57
- moneroTransactionHistory.refreshTransactions();
63
+ monero_transaction_history.refreshTransactions();
64
_isRefreshing = false;
65
} on PlatformException catch (e) {
66
_isRefreshing = false;
67
print(e);
62
- throw e;
68
+ rethrow;
69
}
70
}
71
}
lib/src/domain/monero/monero_wallet.dart
+132
-99
@@ -3,8 +3,8 @@ import 'package:flutter/foundation.dart';
3
import 'package:flutter/services.dart';
4
import 'package:hive/hive.dart';
5
import 'package:rxdart/rxdart.dart';
6
-import 'package:cw_monero/wallet.dart' as moneroWallet;
7
-import 'package:cw_monero/transaction_history.dart' as transactionHistory;
6
+import 'package:cw_monero/wallet.dart' as monero_wallet;
7
+import 'package:cw_monero/transaction_history.dart' as transaction_history;
8
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
9
import 'package:cake_wallet/src/domain/common/wallet.dart';
10
import 'package:cake_wallet/src/domain/common/sync_status.dart';
@@ -23,9 +23,25 @@ import 'package:cake_wallet/src/domain/monero/subaddress.dart';
23
import 'package:cake_wallet/src/domain/common/balance.dart';
24
import 'package:cake_wallet/src/domain/monero/monero_balance.dart';
25
26
-const monero_block_size = 1000;
26
+const moneroBlockSize = 1000;
27
28
class MoneroWallet extends Wallet {
29
+ MoneroWallet({this.walletInfoSource, this.walletInfo}) {
30
+ _cachedBlockchainHeight = 0;
31
+ _isSaving = false;
32
+ _lastSaveTime = 0;
33
+ _lastRefreshTime = 0;
34
+ _refreshHeight = 0;
35
+ _lastSyncHeight = 0;
36
+ _name = BehaviorSubject<String>();
37
+ _address = BehaviorSubject<String>();
38
+ _syncStatus = BehaviorSubject<SyncStatus>();
39
+ _onBalanceChange = BehaviorSubject<MoneroBalance>();
40
+ _account = BehaviorSubject<Account>()..add(Account(id: 0));
41
+ _subaddress = BehaviorSubject<Subaddress>();
42
+ setListeners();
43
+ }
44
+
45
static Future<MoneroWallet> createdWallet(
46
{Box<WalletInfo> walletInfoSource,
47
String name,
@@ -48,8 +64,8 @@ class MoneroWallet extends Wallet {
64
static Future<MoneroWallet> load(
65
Box<WalletInfo> walletInfoSource, String name, WalletType type) async {
66
final id = walletTypeToString(type).toLowerCase() + '_' + name;
51
- final walletInfo =
52
- walletInfoSource.values.firstWhere((info) => info.id == id, orElse: () => null);
67
+ final walletInfo = walletInfoSource.values
68
+ .firstWhere((info) => info.id == id, orElse: () => null);
69
return await configured(
70
walletInfoSource: walletInfoSource, walletInfo: walletInfo);
71
}
@@ -61,29 +77,44 @@ class MoneroWallet extends Wallet {
77
walletInfoSource: walletInfoSource, walletInfo: walletInfo);
78
79
if (walletInfo.isRecovery) {
64
- await wallet.setRecoveringFromSeed();
80
+ wallet.setRecoveringFromSeed();
81
82
if (walletInfo.restoreHeight != null) {
67
- await wallet.setRefreshFromBlockHeight(
68
- height: walletInfo.restoreHeight);
83
+ wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight);
84
}
85
}
86
87
return wallet;
88
}
89
90
+ @override
91
+ String get address => _address.value;
92
+
93
+ @override
94
+ String get name => _name.value;
95
+
96
+ @override
97
WalletType getType() => WalletType.monero;
76
- bool get isRecovery => walletInfo.isRecovery;
98
+
99
+ @override
100
Observable<SyncStatus> get syncStatus => _syncStatus.stream;
101
+
102
+ @override
103
Observable<Balance> get onBalanceChange => _onBalanceChange.stream;
79
- Observable<Account> get onAccountChange => _account.stream;
104
+
105
+ @override
106
Observable<String> get onNameChange => _name.stream;
107
+
108
+ @override
109
Observable<String> get onAddressChange => _address.stream;
110
+
111
+ Observable<Account> get onAccountChange => _account.stream;
112
+
113
Observable<Subaddress> get subaddress => _subaddress.stream;
114
115
+ bool get isRecovery => walletInfo.isRecovery;
116
+
117
Account get account => _account.value;
85
- String get address => _address.value;
86
- String get name => _name.value;
118
119
Box<WalletInfo> walletInfoSource;
120
WalletInfo walletInfo;
@@ -105,27 +136,11 @@ class MoneroWallet extends Wallet {
136
SubaddressList _cachedSubaddressList;
137
AccountList _cachedAccountList;
138
108
- MoneroWallet(
109
- {this.walletInfoSource, this.walletInfo}) {
110
- _cachedBlockchainHeight = 0;
111
- _isSaving = false;
112
- _lastSaveTime = 0;
113
- _lastRefreshTime = 0;
114
- _refreshHeight = 0;
115
- _lastSyncHeight = 0;
116
- _name = BehaviorSubject<String>();
117
- _address = BehaviorSubject<String>();
118
- _syncStatus = BehaviorSubject<SyncStatus>();
119
- _onBalanceChange = BehaviorSubject<MoneroBalance>();
120
- _account = BehaviorSubject<Account>()..add(Account(id: 0));
121
- _subaddress = BehaviorSubject<Subaddress>();
122
- setListeners();
123
- }
124
-
139
+ @override
140
Future updateInfo() async {
141
_name.value = await getName();
142
final acccountList = getAccountList();
128
- await acccountList.refresh();
143
+ acccountList.refresh();
144
_account.value = acccountList.getAll().first;
145
final subaddressList = getSubaddress();
146
await subaddressList.refresh(
@@ -135,44 +150,87 @@ class MoneroWallet extends Wallet {
150
_address.value = await getAddress();
151
}
152
138
- Future<String> getFilename() async => moneroWallet.getFilename();
153
+ @override
154
+ Future<String> getFilename() async => monero_wallet.getFilename();
155
156
+ @override
157
Future<String> getName() async => getFilename()
158
.then((filename) => filename.split('/'))
159
.then((splitted) => splitted.last);
160
144
- Future<String> getAddress() async => moneroWallet.getAddress(
161
+ @override
162
+ Future<String> getAddress() async => monero_wallet.getAddress(
163
accountIndex: _account.value.id, addressIndex: _subaddress.value.id);
164
147
- Future<String> getSeed() async => moneroWallet.getSeed();
165
+ @override
166
+ Future<String> getSeed() async => monero_wallet.getSeed();
167
168
+ @override
169
Future<String> getFullBalance() async => moneroAmountToString(
150
- amount: moneroWallet.getFullBalance(accountIndex: _account.value.id));
170
+ amount: monero_wallet.getFullBalance(accountIndex: _account.value.id));
171
172
+ @override
173
Future<String> getUnlockedBalance() async => moneroAmountToString(
153
- amount: moneroWallet.getUnlockedBalance(accountIndex: _account.value.id));
174
+ amount:
175
+ monero_wallet.getUnlockedBalance(accountIndex: _account.value.id));
176
+
177
+ @override
178
+ Future<int> getCurrentHeight() async => monero_wallet.getCurrentHeight();
179
155
- Future<int> getCurrentHeight() async => moneroWallet.getCurrentHeight();
180
+ @override
181
+ Future<int> getNodeHeight() async => monero_wallet.getNodeHeight();
182
157
- Future<int> getNodeHeight() async => moneroWallet.getNodeHeight();
183
+ @override
184
+ Future<bool> isConnected() async => monero_wallet.isConnected();
185
186
+ @override
187
Future<Map<String, String>> getKeys() async => {
160
- 'publicViewKey': moneroWallet.getPublicViewKey(),
161
- 'privateViewKey': moneroWallet.getSecretViewKey(),
162
- 'publicSpendKey': moneroWallet.getPublicSpendKey(),
163
- 'privateSpendKey': moneroWallet.getSecretSpendKey()
188
+ 'publicViewKey': monero_wallet.getPublicViewKey(),
189
+ 'privateViewKey': monero_wallet.getSecretViewKey(),
190
+ 'publicSpendKey': monero_wallet.getPublicSpendKey(),
191
+ 'privateSpendKey': monero_wallet.getSecretSpendKey()
192
};
193
194
+ @override
195
+ TransactionHistory getHistory() {
196
+ if (_cachedTransactionHistory == null) {
197
+ _cachedTransactionHistory = MoneroTransactionHistory();
198
+ }
199
+
200
+ return _cachedTransactionHistory;
201
+ }
202
+
203
+ SubaddressList getSubaddress() {
204
+ if (_cachedSubaddressList == null) {
205
+ _cachedSubaddressList = SubaddressList();
206
+ }
207
+
208
+ return _cachedSubaddressList;
209
+ }
210
+
211
+ AccountList getAccountList() {
212
+ if (_cachedAccountList == null) {
213
+ _cachedAccountList = AccountList();
214
+ }
215
+
216
+ return _cachedAccountList;
217
+ }
218
+
219
+ @override
220
Future close() async {
167
- moneroWallet.closeListeners();
168
- moneroWallet.closeCurrentWallet();
221
+ monero_wallet.closeListeners();
222
+ monero_wallet.closeCurrentWallet();
223
+ await _name.close();
224
+ await _address.close();
225
+ await _subaddress.close();
226
}
227
228
+ @override
229
Future connectToNode(
230
{Node node, bool useSSL = false, bool isLightWallet = false}) async {
231
try {
232
_syncStatus.value = ConnectingSyncStatus();
175
- await moneroWallet.setupNode(
233
+ await monero_wallet.setupNode(
234
address: node.uri,
235
login: node.login,
236
password: node.password,
@@ -185,39 +243,16 @@ class MoneroWallet extends Wallet {
243
}
244
}
245
246
+ @override
247
Future startSync() async {
248
try {
249
_syncStatus.value = StartingSyncStatus();
191
- moneroWallet.startRefresh();
250
+ monero_wallet.startRefresh();
251
} on PlatformException catch (e) {
252
_syncStatus.value = FailedSyncStatus();
253
print(e);
195
- throw e;
196
- }
197
- }
198
-
199
- TransactionHistory getHistory() {
200
- if (_cachedTransactionHistory == null) {
201
- _cachedTransactionHistory = MoneroTransactionHistory();
202
- }
203
-
204
- return _cachedTransactionHistory;
205
- }
206
-
207
- SubaddressList getSubaddress() {
208
- if (_cachedSubaddressList == null) {
209
- _cachedSubaddressList = SubaddressList();
254
+ rethrow;
255
}
211
-
212
- return _cachedSubaddressList;
213
- }
214
-
215
- AccountList getAccountList() {
216
- if (_cachedAccountList == null) {
217
- _cachedAccountList = AccountList();
218
- }
219
-
220
- return _cachedAccountList;
256
}
257
258
Future askForSave() async {
@@ -238,12 +273,11 @@ class MoneroWallet extends Wallet {
273
return _cachedBlockchainHeight;
274
}
275
276
+ @override
277
Future<PendingTransaction> createTransaction(
278
TransactionCreationCredentials credentials) async {
243
- MoneroTransactionCreationCredentials _credentials =
244
- credentials as MoneroTransactionCreationCredentials;
245
-
246
- final transactionDescription = await transactionHistory.createTransaction(
279
+ final _credentials = credentials as MoneroTransactionCreationCredentials;
280
+ final transactionDescription = await transaction_history.createTransaction(
281
address: _credentials.address,
282
paymentId: _credentials.paymentId,
283
amount: _credentials.amount,
@@ -254,13 +288,19 @@ class MoneroWallet extends Wallet {
288
transactionDescription);
289
}
290
257
- setRecoveringFromSeed() =>
258
- moneroWallet.setRecoveringFromSeed(isRecovery: true);
291
+ @override
292
+ Future rescan({int restoreHeight = 0}) async {
293
+ _syncStatus.value = StartingSyncStatus();
294
+ setRefreshFromBlockHeight(height: restoreHeight);
295
+ monero_wallet.rescanBlockchainAsync();
296
+ _syncStatus.value = StartingSyncStatus();
297
+ }
298
260
- setRefreshFromBlockHeight({int height}) =>
261
- moneroWallet.setRefreshFromBlockHeight(height: height);
299
+ void setRecoveringFromSeed() =>
300
+ monero_wallet.setRecoveringFromSeed(isRecovery: true);
301
263
- Future<bool> isConnected() async => moneroWallet.isConnected();
302
+ void setRefreshFromBlockHeight({int height}) =>
303
+ monero_wallet.setRefreshFromBlockHeight(height: height);
304
305
Future setAsRecovered() async {
306
walletInfo.isRecovery = false;
@@ -285,22 +325,15 @@ class MoneroWallet extends Wallet {
325
326
Future askForUpdateTransactionHistory() async => await getHistory().update();
327
288
- Future rescan({int restoreHeight = 0}) async {
289
- _syncStatus.value = StartingSyncStatus();
290
- setRefreshFromBlockHeight(height: restoreHeight);
291
- moneroWallet.rescanBlockchainAsync();
292
- _syncStatus.value = StartingSyncStatus();
293
- }
294
-
295
- changeCurrentSubaddress(Subaddress subaddress) =>
328
+ void changeCurrentSubaddress(Subaddress subaddress) =>
329
_subaddress.value = subaddress;
330
298
- changeAccount(Account account) {
331
+ void changeAccount(Account account) {
332
_account.add(account);
333
334
getSubaddress()
335
.refresh(accountIndex: account.id)
303
- .then((_) => getSubaddress().getAll())
336
+ .then((dynamic _) => getSubaddress().getAll())
337
.then((subaddresses) => _subaddress.value = subaddresses[0]);
338
}
339
@@ -311,16 +344,16 @@ class MoneroWallet extends Wallet {
344
345
try {
346
_isSaving = true;
314
- moneroWallet.store();
347
+ await monero_wallet.store();
348
_isSaving = false;
349
} on PlatformException catch (e) {
350
print(e);
351
_isSaving = false;
319
- throw e;
352
+ rethrow;
353
}
354
}
355
323
- setListeners() => moneroWallet.setListeners(
356
+ void setListeners() => monero_wallet.setListeners(
357
_onNewBlock, _onNeedToRefresh, _onNewTransaction);
358
359
Future _onNewBlock(int height) async {
@@ -333,13 +366,13 @@ class MoneroWallet extends Wallet {
366
367
if (isRecovery &&
368
(_lastSyncHeight == 0 ||
336
- (height - _lastSyncHeight) > monero_block_size)) {
369
+ (height - _lastSyncHeight) > moneroBlockSize)) {
370
_lastSyncHeight = height;
338
- askForUpdateBalance();
339
- askForUpdateTransactionHistory();
371
+ await askForUpdateBalance();
372
+ await askForUpdateTransactionHistory();
373
}
374
342
- if (height > 0 && ((nodeHeight - height) < monero_block_size)) {
375
+ if (height > 0 && ((nodeHeight - height) < moneroBlockSize)) {
376
_syncStatus.add(SyncedSyncStatus());
377
} else {
378
_syncStatus.add(SyncingSyncStatus(height, nodeHeight, _refreshHeight));
@@ -363,15 +396,15 @@ class MoneroWallet extends Wallet {
396
return;
397
}
398
366
- askForUpdateBalance();
399
+ await askForUpdateBalance();
400
401
_syncStatus.add(SyncedSyncStatus());
402
403
if (isRecovery) {
371
- askForUpdateTransactionHistory();
404
+ await askForUpdateTransactionHistory();
405
}
406
374
- if (isRecovery && (nodeHeight - currentHeight < monero_block_size)) {
407
+ if (isRecovery && (nodeHeight - currentHeight < moneroBlockSize)) {
408
await setAsRecovered();
409
}
410
lib/src/domain/monero/monero_wallets_manager.dart
+35
-24
@@ -3,7 +3,7 @@ import 'dart:io';
3
import 'package:flutter/foundation.dart';
4
import 'package:hive/hive.dart';
5
import 'package:path_provider/path_provider.dart';
6
-import 'package:cw_monero/wallet_manager.dart' as moneroWalletManager;
6
+import 'package:cw_monero/wallet_manager.dart' as monero_wallet_manager;
7
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
8
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
9
import 'package:cake_wallet/src/domain/common/wallets_manager.dart';
@@ -24,54 +24,61 @@ Future<String> pathForWallet({String name}) async {
24
}
25
26
class MoneroWalletsManager extends WalletsManager {
27
+ MoneroWalletsManager({@required this.walletInfoSource});
28
+
29
static const type = WalletType.monero;
30
31
Box<WalletInfo> walletInfoSource;
32
31
- MoneroWalletsManager({@required this.walletInfoSource});
32
-
33
+ @override
34
Future<Wallet> create(String name, String password) async {
35
try {
36
const isRecovery = false;
37
final path = await pathForWallet(name: name);
38
38
- await moneroWalletManager.createWallet(path: path, password: password);
39
+ await monero_wallet_manager.createWallet(path: path, password: password);
40
41
final wallet = await MoneroWallet.createdWallet(
41
- walletInfoSource: walletInfoSource, name: name, isRecovery: isRecovery)
42
- ..updateInfo();
42
+ walletInfoSource: walletInfoSource,
43
+ name: name,
44
+ isRecovery: isRecovery);
45
+ await wallet.updateInfo();
46
47
return wallet;
48
} catch (e) {
49
print('MoneroWalletsManager Error: $e');
47
- throw e;
50
+ rethrow;
51
}
52
}
53
54
+ @override
55
Future<Wallet> restoreFromSeed(
56
String name, String password, String seed, int restoreHeight) async {
57
try {
58
const isRecovery = true;
59
final path = await pathForWallet(name: name);
60
57
- await moneroWalletManager.restoreFromSeed(
61
+ await monero_wallet_manager.restoreFromSeed(
62
path: path,
63
password: password,
64
seed: seed,
65
restoreHeight: restoreHeight);
66
63
- return await MoneroWallet.createdWallet(
67
+ final wallet = await MoneroWallet.createdWallet(
68
walletInfoSource: walletInfoSource,
69
name: name,
70
isRecovery: isRecovery,
67
- restoreHeight: restoreHeight)
68
- ..updateInfo();
71
+ restoreHeight: restoreHeight);
72
+ await wallet.updateInfo();
73
+
74
+ return wallet;
75
} catch (e) {
76
print('MoneroWalletsManager Error: $e');
71
- throw e;
77
+ rethrow;
78
}
79
}
80
81
+ @override
82
Future<Wallet> restoreFromKeys(
83
String name,
84
String password,
@@ -83,7 +90,7 @@ class MoneroWalletsManager extends WalletsManager {
90
const isRecovery = true;
91
final path = await pathForWallet(name: name);
92
86
- await moneroWalletManager.restoreFromKeys(
93
+ await monero_wallet_manager.restoreFromKeys(
94
path: path,
95
password: password,
96
restoreHeight: restoreHeight,
@@ -95,40 +102,43 @@ class MoneroWalletsManager extends WalletsManager {
102
walletInfoSource: walletInfoSource,
103
name: name,
104
isRecovery: isRecovery,
98
- restoreHeight: restoreHeight)
99
- ..updateInfo();
105
+ restoreHeight: restoreHeight);
106
+ await wallet.updateInfo();
107
108
return wallet;
109
} catch (e) {
110
print('MoneroWalletsManager Error: $e');
104
- throw e;
111
+ rethrow;
112
}
113
}
114
115
+ @override
116
Future<Wallet> openWallet(String name, String password) async {
117
try {
118
final path = await pathForWallet(name: name);
111
- await moneroWalletManager.openWallet(path: path, password: password);
112
- final wallet = await MoneroWallet.load(walletInfoSource, name, type)
113
- ..updateInfo();
119
+ monero_wallet_manager.openWallet(path: path, password: password);
120
+ final wallet = await MoneroWallet.load(walletInfoSource, name, type);
121
+ await wallet.updateInfo();
122
123
return wallet;
124
} catch (e) {
125
print('MoneroWalletsManager Error: $e');
118
- throw e;
126
+ rethrow;
127
}
128
}
129
130
+ @override
131
Future<bool> isWalletExit(String name) async {
132
try {
133
final path = await pathForWallet(name: name);
125
- return moneroWalletManager.isWalletExist(path: path);
134
+ return monero_wallet_manager.isWalletExist(path: path);
135
} catch (e) {
136
print('MoneroWalletsManager Error: $e');
128
- throw e;
137
+ rethrow;
138
}
139
}
140
141
+ @override
142
Future remove(WalletDescription wallet) async {
143
final dir = await getApplicationDocumentsDirectory();
144
final root = dir.path.replaceAll('app_flutter', 'files');
@@ -153,8 +163,9 @@ class MoneroWalletsManager extends WalletsManager {
163
164
final id =
165
walletTypeToString(wallet.type).toLowerCase() + '_' + wallet.name;
156
- final info = walletInfoSource.values.firstWhere((info) => info.id == id, orElse: () => null);
157
-
166
+ final info = walletInfoSource.values
167
+ .firstWhere((info) => info.id == id, orElse: () => null);
168
+
169
await info?.delete();
170
}
171
}
lib/src/domain/monero/subaddress.dart
+7
-7
@@ -1,19 +1,19 @@
1
import 'package:cw_monero/structs/subaddress_row.dart';
2
3
class Subaddress {
4
- final int id;
5
- final String address;
6
- final String label;
7
-
4
Subaddress({this.id, this.address, this.label});
5
6
Subaddress.fromMap(Map map)
11
- : this.id = map['id'] == null ? 0 : int.parse(map['id']),
12
- this.address = map['address'] ?? '',
13
- this.label = map['label'] ?? '';
7
+ : this.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
8
+ this.address = (map['address'] ?? '') as String,
9
+ this.label = (map['label'] ?? '') as String;
10
11
Subaddress.fromRow(SubaddressRow row)
12
: this.id = row.getId(),
13
this.address = row.getAddress(),
14
this.label = row.getLabel();
15
+
16
+ final int id;
17
+ final String address;
18
+ final String label;
19
}
lib/src/domain/monero/subaddress_list.dart
+14
-13
@@ -1,21 +1,21 @@
1
import 'package:flutter/services.dart';
2
import 'package:rxdart/rxdart.dart';
3
-import 'package:cw_monero/subaddress_list.dart' as subaddressListAPI;
3
+import 'package:cw_monero/subaddress_list.dart' as subaddress_list;
4
import 'package:cake_wallet/src/domain/monero/subaddress.dart';
5
6
class SubaddressList {
7
- get subaddresses => _subaddress.stream;
8
- BehaviorSubject<List<Subaddress>> _subaddress;
9
-
10
- bool _isRefreshing;
11
- bool _isUpdating;
12
-
7
SubaddressList() {
8
_isRefreshing = false;
9
_isUpdating = false;
10
_subaddress = BehaviorSubject<List<Subaddress>>();
11
}
12
13
+ Observable<List<Subaddress>> get subaddresses => _subaddress.stream;
14
+
15
+ BehaviorSubject<List<Subaddress>> _subaddress;
16
+ bool _isRefreshing;
17
+ bool _isUpdating;
18
+
19
Future update({int accountIndex}) async {
20
if (_isUpdating) {
21
return;
@@ -29,25 +29,26 @@ class SubaddressList {
29
_isUpdating = false;
30
} catch (e) {
31
_isUpdating = false;
32
- throw e;
32
+ rethrow;
33
}
34
}
35
36
List<Subaddress> getAll() {
37
- return subaddressListAPI
37
+ return subaddress_list
38
.getAllSubaddresses()
39
.map((subaddressRow) => Subaddress.fromRow(subaddressRow))
40
.toList();
41
}
42
43
Future addSubaddress({int accountIndex, String label}) async {
44
- await subaddressListAPI.addSubaddress(accountIndex: accountIndex, label: label);
44
+ await subaddress_list.addSubaddress(
45
+ accountIndex: accountIndex, label: label);
46
await update(accountIndex: accountIndex);
47
}
48
49
Future setLabelSubaddress(
50
{int accountIndex, int addressIndex, String label}) async {
50
- await subaddressListAPI.setLabelForSubaddress(
51
+ await subaddress_list.setLabelForSubaddress(
52
accountIndex: accountIndex, addressIndex: addressIndex, label: label);
53
await update();
54
}
@@ -59,12 +60,12 @@ class SubaddressList {
60
61
try {
62
_isRefreshing = true;
62
- subaddressListAPI.refreshSubaddresses(accountIndex: accountIndex);
63
+ subaddress_list.refreshSubaddresses(accountIndex: accountIndex);
64
_isRefreshing = false;
65
} on PlatformException catch (e) {
66
_isRefreshing = false;
67
print(e);
67
- throw e;
68
+ rethrow;
69
}
70
}
71
}
lib/src/domain/monero/transaction_description.dart
+3
-3
@@ -4,6 +4,8 @@ part 'transaction_description.g.dart';
4
5
@HiveType()
6
class TransactionDescription extends HiveObject {
7
+ TransactionDescription({this.id, this.recipientAddress});
8
+
9
static const boxName = 'TransactionDescriptions';
10
11
@HiveField(0)
@@ -11,6 +13,4 @@ class TransactionDescription extends HiveObject {
13
14
@HiveField(1)
15
String recipientAddress;
14
-
15
- TransactionDescription({this.id, this.recipientAddress});
16
-}
\ No newline at end of file
16
+}
lib/src/domain/services/user_service.dart
+2
-2
@@ -4,11 +4,11 @@ import 'package:cake_wallet/src/domain/common/secret_store_key.dart';
4
import 'package:cake_wallet/src/domain/common/encrypt.dart';
5
6
class UserService {
7
+ UserService({this.sharedPreferences, this.secureStorage});
8
+
9
final FlutterSecureStorage secureStorage;
10
final SharedPreferences sharedPreferences;
11
10
- UserService({this.sharedPreferences, this.secureStorage});
11
-
12
Future setPassword(String password) async {
13
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
14
lib/src/domain/services/wallet_list_service.dart
+10
-10
@@ -15,21 +15,15 @@ import 'package:cake_wallet/src/domain/monero/monero_wallets_manager.dart';
15
import 'package:cake_wallet/src/domain/services/wallet_service.dart';
16
17
class WalletIsExistException implements Exception {
18
- String name;
19
-
18
WalletIsExistException(this.name);
19
20
+ String name;
21
+
22
@override
23
String toString() => "Wallet with name $name is already exist!";
24
}
25
26
class WalletListService {
27
- final FlutterSecureStorage secureStorage;
28
- final WalletService walletService;
29
- final Box<WalletInfo> walletInfoSource;
30
- final SharedPreferences sharedPreferences;
31
- WalletsManager walletsManager;
32
-
27
WalletListService(
28
{this.secureStorage,
29
this.walletInfoSource,
@@ -37,6 +31,12 @@ class WalletListService {
31
@required this.walletService,
32
@required this.sharedPreferences});
33
34
+ final FlutterSecureStorage secureStorage;
35
+ final WalletService walletService;
36
+ final Box<WalletInfo> walletInfoSource;
37
+ final SharedPreferences sharedPreferences;
38
+ WalletsManager walletsManager;
39
+
40
Future<List<WalletDescription>> getAll() async => walletInfoSource.values
41
.map((info) => WalletDescription(name: info.name, type: info.type))
42
.toList();
@@ -52,7 +52,7 @@ class WalletListService {
52
53
final password = Uuid().v4();
54
await saveWalletPassword(password: password, walletName: name);
55
-
55
+
56
final wallet = await walletsManager.create(name, password);
57
58
await onWalletChange(wallet);
@@ -131,7 +131,7 @@ class WalletListService {
131
final key = generateStoreKeyFor(
132
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
133
final encodedPassword = await secureStorage.read(key: key);
134
-
134
+
135
return decodeWalletPassword(password: encodedPassword);
136
}
137
lib/src/domain/services/wallet_service.dart
+49
-16
@@ -10,17 +10,40 @@ import 'package:cake_wallet/src/domain/common/pending_transaction.dart';
10
import 'package:cake_wallet/src/domain/common/node.dart';
11
12
class WalletService extends Wallet {
13
- Observable<Wallet> get onWalletChange => _onWalletChanged.stream;
13
+ WalletService() {
14
+ _currentWallet = null;
15
+ walletType = WalletType.none;
16
+ _syncStatus = BehaviorSubject<SyncStatus>();
17
+ _onBalanceChange = BehaviorSubject<Balance>();
18
+ _onWalletChanged = BehaviorSubject<Wallet>();
19
+ }
20
+
21
+ @override
22
Observable<Balance> get onBalanceChange => _onBalanceChange.stream;
23
+
24
+ @override
25
Observable<SyncStatus> get syncStatus => _syncStatus.stream;
26
+
27
+ @override
28
Observable<String> get onAddressChange => _currentWallet.onAddressChange;
29
+
30
+ @override
31
Observable<String> get onNameChange => _currentWallet.onNameChange;
32
+
33
+ @override
34
String get address => _currentWallet.address;
35
+
36
+ @override
37
String get name => _currentWallet.name;
20
- SyncStatus get syncStatusValue => _syncStatus.value;
38
+
39
+ @override
40
WalletType get walletType => _currentWallet.walletType;
41
23
- get currentWallet => _currentWallet;
42
+ Observable<Wallet> get onWalletChange => _onWalletChanged.stream;
43
+
44
+ SyncStatus get syncStatusValue => _syncStatus.value;
45
+
46
+ Wallet get currentWallet => _currentWallet;
47
48
set currentWallet(Wallet wallet) {
49
_currentWallet = wallet;
@@ -44,55 +67,65 @@ class WalletService extends Wallet {
67
BehaviorSubject<SyncStatus> _syncStatus;
68
Wallet _currentWallet;
69
47
- WalletService() {
48
- _currentWallet = null;
49
- walletType = WalletType.none;
50
- _syncStatus = BehaviorSubject<SyncStatus>();
51
- _onBalanceChange = BehaviorSubject<Balance>();
52
- _onWalletChanged = BehaviorSubject<Wallet>();
53
- }
54
-
70
WalletDescription description;
71
72
+ @override
73
WalletType getType() => WalletType.monero;
74
75
+ @override
76
Future<String> getFilename() => _currentWallet.getFilename();
77
78
+ @override
79
Future<String> getName() => _currentWallet.getName();
80
81
+ @override
82
Future<String> getAddress() => _currentWallet.getAddress();
83
84
+ @override
85
Future<String> getSeed() => _currentWallet.getSeed();
86
87
+ @override
88
Future<Map<String, String>> getKeys() => _currentWallet.getKeys();
89
90
+ @override
91
Future<String> getFullBalance() => _currentWallet.getFullBalance();
92
93
+ @override
94
Future<String> getUnlockedBalance() => _currentWallet.getUnlockedBalance();
95
96
+ @override
97
Future<int> getCurrentHeight() => _currentWallet.getCurrentHeight();
98
99
+ @override
100
Future<int> getNodeHeight() => _currentWallet.getNodeHeight();
101
102
+ @override
103
Future<bool> isConnected() => _currentWallet.isConnected();
104
105
+ @override
106
Future close() => _currentWallet.close();
107
81
- Future connectToNode({Node node, bool useSSL = false, bool isLightWallet = false}) =>
108
+ @override
109
+ Future connectToNode(
110
+ {Node node, bool useSSL = false, bool isLightWallet = false}) =>
111
_currentWallet.connectToNode(
83
- node: node,
84
- useSSL: useSSL,
85
- isLightWallet: isLightWallet);
112
+ node: node, useSSL: useSSL, isLightWallet: isLightWallet);
113
114
+ @override
115
Future startSync() => _currentWallet.startSync();
116
117
+ @override
118
TransactionHistory getHistory() => _currentWallet.getHistory();
119
120
+ @override
121
Future<PendingTransaction> createTransaction(
122
TransactionCreationCredentials credentials) =>
123
_currentWallet.createTransaction(credentials);
124
125
+ @override
126
Future updateInfo() async => _currentWallet.updateInfo();
127
97
- Future rescan({int restoreHeight = 0}) async => _currentWallet.rescan(restoreHeight: restoreHeight);
128
+ @override
129
+ Future rescan({int restoreHeight = 0}) async =>
130
+ _currentWallet.rescan(restoreHeight: restoreHeight);
131
}
lib/src/reactions/set_reactions.dart
+41
-29
@@ -1,6 +1,7 @@
1
import 'dart:async';
2
import 'package:flutter/foundation.dart';
3
import 'package:mobx/mobx.dart';
4
+import 'package:cake_wallet/src/domain/common/node.dart';
5
import 'package:cake_wallet/src/domain/common/sync_status.dart';
6
import 'package:cake_wallet/src/domain/services/wallet_service.dart';
7
import 'package:cake_wallet/src/start_updating_price.dart';
@@ -11,7 +12,12 @@ import 'package:cake_wallet/src/stores/price/price_store.dart';
12
import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
13
import 'package:cake_wallet/src/stores/login/login_store.dart';
14
14
-setReactions(
15
+Timer _reconnectionTimer;
16
+ReactionDisposer _connectToNodeDisposer;
17
+ReactionDisposer _onSyncStatusChangeDisposer;
18
+ReactionDisposer _onCurrentWalletChangeDisposer;
19
+
20
+void setReactions(
21
{@required SettingsStore settingsStore,
22
@required PriceStore priceStore,
23
@required SyncStore syncStore,
@@ -36,29 +42,44 @@ setReactions(
42
});
43
}
44
39
-connectToNode({SettingsStore settingsStore, WalletStore walletStore}) =>
40
- reaction((_) => settingsStore.node,
41
- (node) async => await walletStore.connectToNode(node: node));
45
+void connectToNode({SettingsStore settingsStore, WalletStore walletStore}) {
46
+ _connectToNodeDisposer?.call();
47
43
-onSyncStatusChange(
44
- {SyncStore syncStore,
45
- WalletStore walletStore,
46
- SettingsStore settingsStore}) =>
47
- reaction((_) => syncStore.status, (status) async {
48
- if (status is ConnectedSyncStatus) {
49
- await walletStore.startSync();
50
- }
48
+ _connectToNodeDisposer = reaction((_) => settingsStore.node,
49
+ (Node node) async => await walletStore.connectToNode(node: node));
50
+}
51
52
- // Reconnect to the node if the app is not started sync after 30 seconds
53
- if (status is StartingSyncStatus) {
54
- await startReconnectionObserver(
55
- syncStore: syncStore, walletStore: walletStore);
56
- }
57
- });
52
+void onCurrentWalletChange(
53
+ {WalletStore walletStore,
54
+ SettingsStore settingsStore,
55
+ PriceStore priceStore}) {
56
+ _onCurrentWalletChangeDisposer?.call();
57
59
-Timer _reconnectionTimer;
58
+ reaction((_) => walletStore.name, (String _) {
59
+ walletStore.connectToNode(node: settingsStore.node);
60
+ startUpdatingPrice(settingsStore: settingsStore, priceStore: priceStore);
61
+ });
62
+}
63
61
-startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) {
64
+void onSyncStatusChange(
65
+ {SyncStore syncStore,
66
+ WalletStore walletStore,
67
+ SettingsStore settingsStore}) {
68
+ _onSyncStatusChangeDisposer?.call();
69
+
70
+ reaction((_) => syncStore.status, (SyncStatus status) async {
71
+ if (status is ConnectedSyncStatus) {
72
+ await walletStore.startSync();
73
+ }
74
+
75
+ // Reconnect to the node if the app is not started sync after 30 seconds
76
+ if (status is StartingSyncStatus) {
77
+ startReconnectionObserver(syncStore: syncStore, walletStore: walletStore);
78
+ }
79
+ });
80
+}
81
+
82
+void startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) {
83
if (_reconnectionTimer != null) {
84
_reconnectionTimer.cancel();
85
}
@@ -75,12 +96,3 @@ startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) {
96
}
97
});
98
}
78
-
79
-onCurrentWalletChange(
80
- {WalletStore walletStore,
81
- SettingsStore settingsStore,
82
- PriceStore priceStore}) =>
83
- reaction((_) => walletStore.name, (_) {
84
- walletStore.connectToNode(node: settingsStore.node);
85
- startUpdatingPrice(settingsStore: settingsStore, priceStore: priceStore);
86
- });
lib/src/screens/accounts/account_list_page.dart
+15
-15
@@ -11,6 +11,7 @@ import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
11
import 'package:cake_wallet/src/screens/base_page.dart';
12
13
class AccountListPage extends BasePage {
14
+ @override
15
String get title => S.current.accounts;
16
17
@override
@@ -21,8 +22,7 @@ class AccountListPage extends BasePage {
22
width: 28.0,
23
height: 28.0,
24
decoration: BoxDecoration(
24
- shape: BoxShape.circle,
25
- color: Theme.of(context).selectedRowColor),
25
+ shape: BoxShape.circle, color: Theme.of(context).selectedRowColor),
26
child: Stack(
27
alignment: Alignment.center,
28
children: <Widget>[
@@ -35,7 +35,7 @@ class AccountListPage extends BasePage {
35
onPressed: () async {
36
await Navigator.of(context)
37
.pushNamed(Routes.accountCreation);
38
- await accountListStore.updateAccountList();
38
+ accountListStore.updateAccountList();
39
},
40
child: Offstage()),
41
)
@@ -53,13 +53,10 @@ class AccountListPage extends BasePage {
53
54
return Container(
55
padding: EdgeInsets.only(top: 10, bottom: 20),
56
- child: Observer(
57
- builder: (_) {
58
- final accounts = accountListStore.accounts;
59
- return ListView.builder(
60
- itemCount: accounts == null
61
- ? 0
62
- : accounts.length,
56
+ child: Observer(builder: (_) {
57
+ final accounts = accountListStore.accounts;
58
+ return ListView.builder(
59
+ itemCount: accounts == null ? 0 : accounts.length,
60
itemBuilder: (BuildContext context, int index) {
61
final account = accounts[index];
62
@@ -78,7 +75,10 @@ class AccountListPage extends BasePage {
75
account.label,
76
style: TextStyle(
77
fontSize: 16.0,
81
- color: Theme.of(context).primaryTextTheme.headline.color),
78
+ color: Theme.of(context)
79
+ .primaryTextTheme
80
+ .headline
81
+ .color),
82
),
83
onTap: () {
84
if (isCurrent) {
@@ -102,8 +102,9 @@ class AccountListPage extends BasePage {
102
color: Colors.blue,
103
icon: Icons.edit,
104
onTap: () async {
105
- await Navigator.of(context)
106
- .pushNamed(Routes.accountCreation, arguments: account);
105
+ await Navigator.of(context).pushNamed(
106
+ Routes.accountCreation,
107
+ arguments: account);
108
// await accountListStore.updateAccountList().then((_) {
109
// if (isCurrent) walletStore.setAccount(accountListStore.accounts[index]);
110
// });
@@ -113,8 +114,7 @@ class AccountListPage extends BasePage {
114
);
115
});
116
});
116
- }
117
- ),
117
+ }),
118
);
119
}
120
}
lib/src/screens/accounts/account_page.dart
+10
-8
@@ -10,22 +10,24 @@ import 'package:cake_wallet/src/domain/monero/account.dart';
10
import 'package:cake_wallet/palette.dart';
11
12
class AccountPage extends BasePage {
13
- String get title => 'Account';
13
+ AccountPage({this.account});
14
+
15
final Account account;
16
16
- AccountPage({this.account});
17
+ @override
18
+ String get title => 'Account';
19
20
@override
21
Widget body(BuildContext context) => AccountForm(account);
22
}
23
24
class AccountForm extends StatefulWidget {
23
- final Account account;
24
-
25
AccountForm(this.account);
26
27
+ final Account account;
28
+
29
@override
28
- createState() => AccountFormState();
30
+ AccountFormState createState() => AccountFormState();
31
}
32
33
class AccountFormState extends State<AccountForm> {
@@ -61,8 +63,8 @@ class AccountFormState extends State<AccountForm> {
63
hintStyle: TextStyle(color: Theme.of(context).hintColor),
64
hintText: S.of(context).account,
65
focusedBorder: UnderlineInputBorder(
64
- borderSide: BorderSide(
65
- color: Palette.cakeGreen, width: 2.0)),
66
+ borderSide:
67
+ BorderSide(color: Palette.cakeGreen, width: 2.0)),
68
enabledBorder: UnderlineInputBorder(
69
borderSide: BorderSide(
70
color: Theme.of(context).focusColor, width: 1.0))),
@@ -88,7 +90,7 @@ class AccountFormState extends State<AccountForm> {
90
await accountListStore.addAccount(
91
label: _textController.text);
92
}
91
- Navigator.pop(context, _textController.text);
93
+ Navigator.of(context).pop(_textController.text);
94
},
95
text:
96
widget.account != null ? 'Rename' : S.of(context).add,
lib/src/screens/address_book/address_book_page.dart
+87
-81
@@ -12,13 +12,18 @@ import 'package:cake_wallet/src/stores/address_book/address_book_store.dart';
12
import 'package:cake_wallet/src/screens/base_page.dart';
13
14
class AddressBookPage extends BasePage {
15
- bool get isModalBackButton => true;
16
- String get title => S.current.address_book;
17
- AppBarStyle get appBarStyle => AppBarStyle.withShadow;
15
+ AddressBookPage({this.isEditable = true});
16
17
final bool isEditable;
18
21
- AddressBookPage({this.isEditable = true});
19
+ @override
20
+ bool get isModalBackButton => true;
21
+
22
+ @override
23
+ String get title => S.current.address_book;
24
+
25
+ @override
26
+ AppBarStyle get appBarStyle => AppBarStyle.withShadow;
27
28
@override
29
Widget trailing(BuildContext context) {
@@ -32,8 +37,7 @@ class AddressBookPage extends BasePage {
37
width: 28.0,
38
height: 28.0,
39
decoration: BoxDecoration(
35
- shape: BoxShape.circle,
36
- color: Theme.of(context).selectedRowColor),
40
+ shape: BoxShape.circle, color: Theme.of(context).selectedRowColor),
41
child: Stack(
42
alignment: Alignment.center,
43
children: <Widget>[
@@ -79,16 +83,17 @@ class AddressBookPage extends BasePage {
83
return;
84
}
85
82
- bool isCopied = await showNameAndAddressDialog(context, contact.name, contact.address);
86
+ final isCopied = await showNameAndAddressDialog(
87
+ context, contact.name, contact.address);
88
+
89
if (isCopied) {
84
- Clipboard.setData(ClipboardData(text: contact.address));
90
+ await Clipboard.setData(
91
+ ClipboardData(text: contact.address));
92
Scaffold.of(context).showSnackBar(
93
SnackBar(
87
- content:
88
- Text('Copied to Clipboard'),
94
+ content: Text('Copied to Clipboard'),
95
backgroundColor: Colors.green,
90
- duration:
91
- Duration(milliseconds: 1500),
96
+ duration: Duration(milliseconds: 1500),
97
),
98
);
99
}
@@ -117,48 +122,51 @@ class AddressBookPage extends BasePage {
122
),
123
);
124
120
- return !isEditable ? content
121
- : Slidable(
122
- key: Key('1'),// Key(contact.id.toString()),
123
- actionPane: SlidableDrawerActionPane(),
124
- child: content,
125
- secondaryActions: <Widget>[
126
- IconSlideAction(
127
- caption: 'Edit',
128
- color: Colors.blue,
129
- icon: Icons.edit,
130
- onTap: () async {
131
- await Navigator.of(context)
132
- .pushNamed(Routes.addressBookAddContact, arguments: contact);
133
- await addressBookStore.updateContactList();
134
- },
135
- ),
136
- IconSlideAction(
137
- caption: 'Delete',
138
- color: Colors.red,
139
- icon: CupertinoIcons.delete,
140
- onTap: () async {
141
- await showAlertDialog(context).then((isDelete) async{
142
- if (isDelete != null && isDelete) {
143
- await addressBookStore.delete(contact: contact);
125
+ return !isEditable
126
+ ? content
127
+ : Slidable(
128
+ key: Key('${contact.key}'),
129
+ actionPane: SlidableDrawerActionPane(),
130
+ child: content,
131
+ secondaryActions: <Widget>[
132
+ IconSlideAction(
133
+ caption: 'Edit',
134
+ color: Colors.blue,
135
+ icon: Icons.edit,
136
+ onTap: () async {
137
+ await Navigator.of(context).pushNamed(
138
+ Routes.addressBookAddContact,
139
+ arguments: contact);
140
await addressBookStore.updateContactList();
145
- }
146
- });
147
- },
148
- ),
149
- ],
150
- dismissal: SlidableDismissal(
151
- child: SlidableDrawerDismissal(),
152
- onDismissed: (actionType) async {
153
- await addressBookStore.delete(contact: contact);
154
- await addressBookStore.updateContactList();
155
- },
156
- onWillDismiss: (actionType) async {
157
- return await showAlertDialog(context);
158
- },
159
- ),
160
-
161
- );
141
+ },
142
+ ),
143
+ IconSlideAction(
144
+ caption: 'Delete',
145
+ color: Colors.red,
146
+ icon: CupertinoIcons.delete,
147
+ onTap: () async {
148
+ await showAlertDialog(context)
149
+ .then((isDelete) async {
150
+ if (isDelete != null && isDelete) {
151
+ await addressBookStore.delete(
152
+ contact: contact);
153
+ await addressBookStore.updateContactList();
154
+ }
155
+ });
156
+ },
157
+ ),
158
+ ],
159
+ dismissal: SlidableDismissal(
160
+ child: SlidableDrawerDismissal(),
161
+ onDismissed: (actionType) async {
162
+ await addressBookStore.delete(contact: contact);
163
+ await addressBookStore.updateContactList();
164
+ },
165
+ onWillDismiss: (actionType) async {
166
+ return await showAlertDialog(context);
167
+ },
168
+ ),
169
+ );
170
}),
171
));
172
}
@@ -220,42 +228,40 @@ class AddressBookPage extends BasePage {
228
),
229
actions: <Widget>[
230
FlatButton(
223
- onPressed: () =>
224
- Navigator.pop(context, false),
231
+ onPressed: () => Navigator.of(context).pop( false),
232
child: const Text('Cancel')),
233
FlatButton(
227
- onPressed: () =>
228
- Navigator.pop(context, true),
234
+ onPressed: () => Navigator.of(context).pop(true),
235
child: const Text('Remove')),
236
],
237
);
238
});
239
}
240
235
- showNameAndAddressDialog(BuildContext context, String name, String address) async {
241
+ Future<bool> showNameAndAddressDialog(
242
+ BuildContext context, String name, String address) async {
243
return await showDialog(
237
- context: context,
238
- builder: (BuildContext context) {
239
- return AlertDialog(
240
- title: Text(
241
- name,
242
- textAlign: TextAlign.center,
243
- style: TextStyle(fontWeight: FontWeight.bold),
244
- ),
245
- content: Text(
246
- address,
247
- textAlign: TextAlign.center,
248
- ),
249
- actions: <Widget>[
250
- FlatButton(
251
- onPressed: () => Navigator.of(context).pop(false),
252
- child: Text('Cancel')),
253
- FlatButton(
254
- onPressed: () => Navigator.of(context).pop(true),
255
- child: Text('Copy'))
256
- ],
257
- );
258
- }
259
- );
244
+ context: context,
245
+ builder: (BuildContext context) {
246
+ return AlertDialog(
247
+ title: Text(
248
+ name,
249
+ textAlign: TextAlign.center,
250
+ style: TextStyle(fontWeight: FontWeight.bold),
251
+ ),
252
+ content: Text(
253
+ address,
254
+ textAlign: TextAlign.center,
255
+ ),
256
+ actions: <Widget>[
257
+ FlatButton(
258
+ onPressed: () => Navigator.of(context).pop(false),
259
+ child: Text('Cancel')),
260
+ FlatButton(
261
+ onPressed: () => Navigator.of(context).pop(true),
262
+ child: Text('Copy'))
263
+ ],
264
+ );
265
+ });
266
}
267
}
lib/src/screens/address_book/contact_page.dart
+20
-16
@@ -12,22 +12,24 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
12
import 'package:cake_wallet/palette.dart';
13
14
class ContactPage extends BasePage {
15
- String get title => S.current.contact;
15
+ ContactPage({this.contact});
16
+
17
final Contact contact;
18
18
- ContactPage({this.contact});
19
+ @override
20
+ String get title => S.current.contact;
21
22
@override
23
Widget body(BuildContext context) => ContactForm(contact);
24
}
25
26
class ContactForm extends StatefulWidget {
25
- final Contact contact;
26
-
27
ContactForm(this.contact);
28
29
+ final Contact contact;
30
+
31
@override
30
- createState() => ContactFormState();
32
+ State<ContactForm> createState() => ContactFormState();
33
}
34
35
class ContactFormState extends State<ContactForm> {
@@ -59,10 +61,11 @@ class ContactFormState extends State<ContactForm> {
61
super.dispose();
62
}
63
62
- _setCurrencyType(BuildContext context) async {
63
- String currencyType = CryptoCurrency.all[0].toString();
64
- CryptoCurrency selectedCurrency = CryptoCurrency.all[0];
65
- await showDialog(
64
+ Future<void> _setCurrencyType(BuildContext context) async {
65
+ var currencyType = CryptoCurrency.all[0].toString();
66
+ var selectedCurrency = CryptoCurrency.all[0];
67
+
68
+ await showDialog<void>(
69
context: context,
70
builder: (BuildContext context) {
71
return AlertDialog(
@@ -127,8 +130,8 @@ class ContactFormState extends State<ContactForm> {
130
hintStyle: TextStyle(color: Theme.of(context).hintColor),
131
hintText: S.of(context).contact_name,
132
focusedBorder: UnderlineInputBorder(
130
- borderSide: BorderSide(
131
- color: Palette.cakeGreen, width: 2.0)),
133
+ borderSide:
134
+ BorderSide(color: Palette.cakeGreen, width: 2.0)),
135
enabledBorder: UnderlineInputBorder(
136
borderSide: BorderSide(
137
color: Theme.of(context).focusColor, width: 1.0))),
@@ -153,8 +156,7 @@ class ContactFormState extends State<ContactForm> {
156
decoration: InputDecoration(
157
focusedBorder: UnderlineInputBorder(
158
borderSide: BorderSide(
156
- color: Palette.cakeGreen,
157
- width: 2.0)),
159
+ color: Palette.cakeGreen, width: 2.0)),
160
enabledBorder: UnderlineInputBorder(
161
borderSide: BorderSide(
162
color: Theme.of(context).focusColor,
@@ -215,13 +217,15 @@ class ContactFormState extends State<ContactForm> {
217
} else {
218
widget.contact.name = _contactNameController.text;
219
widget.contact.address = _addressController.text;
218
- widget.contact.updateCryptoCurrency(currency: _selectectCrypto);
220
+ widget.contact
221
+ .updateCryptoCurrency(currency: _selectectCrypto);
222
220
- await addressBookStore.update(contact: widget.contact);
223
+ await addressBookStore.update(
224
+ contact: widget.contact);
225
}
226
Navigator.pop(context);
227
} catch (e) {
224
- await showDialog(
228
+ await showDialog<void>(
229
context: context,
230
builder: (BuildContext context) {
231
return AlertDialog(
lib/src/screens/auth/auth_page.dart
+23
-5
@@ -7,13 +7,14 @@ import 'package:cake_wallet/src/stores/auth/auth_state.dart';
7
import 'package:cake_wallet/src/stores/auth/auth_store.dart';
8
import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
9
10
+typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
11
12
class AuthPage extends StatefulWidget {
12
- final Function(bool, AuthPageState) onAuthenticationFinished;
13
- final bool closable;
14
-
13
AuthPage({this.onAuthenticationFinished, this.closable = true});
14
15
+ final OnAuthenticationFinished onAuthenticationFinished;
16
+ final bool closable;
17
+
18
@override
19
AuthPageState createState() => AuthPageState();
20
}
@@ -33,7 +34,7 @@ class AuthPageState extends State<AuthPage> {
34
Widget build(BuildContext context) {
35
final authStore = Provider.of<AuthStore>(context);
36
36
- reaction((_) => authStore.state, (state) {
37
+ reaction((_) => authStore.state, (AuthState state) {
38
if (state is AuthenticatedSuccessfully) {
39
WidgetsBinding.instance.addPostFrameCallback((_) {
40
if (widget.onAuthenticationFinished != null) {
@@ -60,7 +61,24 @@ class AuthPageState extends State<AuthPage> {
61
});
62
}
63
63
- if (state is AuthenticationFailure || state is AuthenticationBanned) {
64
+ if (state is AuthenticationFailure) {
65
+ WidgetsBinding.instance.addPostFrameCallback((_) {
66
+ _pinCodeKey.currentState.clear();
67
+ _key.currentState.hideCurrentSnackBar();
68
+ _key.currentState.showSnackBar(
69
+ SnackBar(
70
+ content: Text(S.of(context).failed_authentication(state.error)),
71
+ backgroundColor: Colors.red,
72
+ ),
73
+ );
74
+
75
+ if (widget.onAuthenticationFinished != null) {
76
+ widget.onAuthenticationFinished(false, this);
77
+ }
78
+ });
79
+ }
80
+
81
+ if (state is AuthenticationBanned) {
82
WidgetsBinding.instance.addPostFrameCallback((_) {
83
_pinCodeKey.currentState.clear();
84
_key.currentState.hideCurrentSnackBar();
lib/src/screens/base_page.dart
+2
-2
@@ -28,7 +28,7 @@ abstract class BasePage extends StatelessWidget {
28
return null;
29
}
30
31
- ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
31
+ final _themeChanger = Provider.of<ThemeChanger>(context);
32
Image _closeButton, _backButton;
33
34
if (_themeChanger.getTheme() == Themes.darkTheme) {
@@ -70,7 +70,7 @@ abstract class BasePage extends StatelessWidget {
70
71
Widget floatingActionButton(BuildContext context) => null;
72
73
- Widget appBar(BuildContext context) {
73
+ ObstructingPreferredSizeWidget appBar(BuildContext context) {
74
final _themeChanger = Provider.of<ThemeChanger>(context);
75
final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
76
lib/src/screens/dashboard/dashboard_page.dart
+29
-36
@@ -1,6 +1,6 @@
1
import 'package:provider/provider.dart';
2
import 'package:intl/intl.dart';
3
-import 'package:date_range_picker/date_range_picker.dart' as DateRagePicker;
3
+import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
4
import 'package:flutter/material.dart';
5
import 'package:flutter/cupertino.dart';
6
import 'package:flutter_mobx/flutter_mobx.dart';
@@ -86,24 +86,19 @@ class DashboardPage extends BasePage {
86
child: Image.asset('assets/images/exchange_icon.png',
87
color: Colors.white, height: 26, width: 22),
88
backgroundColor: Palette.floatingActionButton,
89
- onPressed: () async {
90
- final actionListStore = Provider.of<ActionListStore>(context);
91
-
92
- await Navigator.of(context, rootNavigator: true)
93
- .pushNamed(Routes.exchange);
94
- actionListStore.updateTradeList();
95
- });
89
+ onPressed: () async => await Navigator.of(context, rootNavigator: true)
90
+ .pushNamed(Routes.exchange));
91
92
void _presentWalletMenu(BuildContext bodyContext) {
93
final walletMenu = WalletMenu(bodyContext);
94
100
- showDialog(
95
+ showDialog<void>(
96
builder: (_) => Picker(
97
items: walletMenu.items,
98
selectedAtIndex: -1,
99
title: S.of(bodyContext).wallet_menu,
100
pickerHeight: 510,
106
- onItemSelected: (item) =>
101
+ onItemSelected: (String item) =>
102
walletMenu.action(walletMenu.items.indexOf(item))),
103
context: bodyContext);
104
}
@@ -136,8 +131,9 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
131
return Observer(
132
key: _listObserverKey,
133
builder: (_) {
139
- final items =
140
- actionListStore.items == null ? [] : actionListStore.items;
134
+ final items = actionListStore.items == null
135
+ ? <String>[]
136
+ : actionListStore.items;
137
final itemsCount = items.length + 2;
138
139
return ListView.builder(
@@ -225,19 +221,17 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
221
builder: (_) {
222
final savedDisplayMode =
223
settingsStore.balanceDisplayMode;
228
- final displayMode =
229
- balanceStore.isReversing
230
- ? (savedDisplayMode ==
231
- BalanceDisplayMode
232
- .availableBalance
233
- ? BalanceDisplayMode
234
- .fullBalance
235
- : BalanceDisplayMode
236
- .availableBalance)
237
- : savedDisplayMode;
238
- var title = displayMode.toString();
239
-
240
- return Text(title,
224
+ final displayMode = balanceStore
225
+ .isReversing
226
+ ? (savedDisplayMode ==
227
+ BalanceDisplayMode
228
+ .availableBalance
229
+ ? BalanceDisplayMode.fullBalance
230
+ : BalanceDisplayMode
231
+ .availableBalance)
232
+ : savedDisplayMode;
233
+
234
+ return Text(displayMode.toString(),
235
style: TextStyle(
236
color: Palette.violet,
237
fontSize: 16));
@@ -248,16 +242,15 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
242
final savedDisplayMode =
243
settingsStore.balanceDisplayMode;
244
var balance = '---';
251
- final displayMode =
252
- balanceStore.isReversing
253
- ? (savedDisplayMode ==
254
- BalanceDisplayMode
255
- .availableBalance
256
- ? BalanceDisplayMode
257
- .fullBalance
258
- : BalanceDisplayMode
259
- .availableBalance)
260
- : savedDisplayMode;
245
+ final displayMode = balanceStore
246
+ .isReversing
247
+ ? (savedDisplayMode ==
248
+ BalanceDisplayMode
249
+ .availableBalance
250
+ ? BalanceDisplayMode.fullBalance
251
+ : BalanceDisplayMode
252
+ .availableBalance)
253
+ : savedDisplayMode;
254
255
if (displayMode ==
256
BalanceDisplayMode.availableBalance) {
@@ -499,7 +492,7 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
492
onSelected: (item) async {
493
if (item == 2) {
494
final List<DateTime> picked =
502
- await DateRagePicker.showDatePicker(
495
+ await date_rage_picker.showDatePicker(
496
context: context,
497
initialFirstDate: DateTime.now()
498
.subtract(Duration(days: 1)),
lib/src/screens/dashboard/date_section_raw.dart
+6
-4
@@ -4,19 +4,21 @@ import 'package:intl/intl.dart';
4
import 'package:cake_wallet/generated/i18n.dart';
5
6
class DateSectionRaw extends StatelessWidget {
7
+ DateSectionRaw({this.date});
8
+
9
static final dateSectionDateFormat = DateFormat("d MMM");
10
static final nowDate = DateTime.now();
11
12
final DateTime date;
13
12
- DateSectionRaw({this.date});
13
-
14
@override
15
Widget build(BuildContext context) {
16
final diffDays = date.difference(nowDate).inDays;
17
- final isToday = nowDate.day == date.day && nowDate.month == date.month && nowDate.year == date.year;
17
+ final isToday = nowDate.day == date.day &&
18
+ nowDate.month == date.month &&
19
+ nowDate.year == date.year;
20
var title = "";
19
-
21
+
22
if (isToday) {
23
title = S.of(context).today;
24
} else if (diffDays == 0) {
lib/src/screens/dashboard/trade_row.dart
+11
-8
@@ -4,13 +4,6 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
4
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
5
6
class TradeRow extends StatelessWidget {
7
- final VoidCallback onTap;
8
- final ExchangeProviderDescription provider;
9
- final CryptoCurrency from;
10
- final CryptoCurrency to;
11
- final String createdAtFormattedDate;
12
- final String formattedAmount;
13
-
7
TradeRow(
8
{this.provider,
9
this.from,
@@ -19,6 +12,13 @@ class TradeRow extends StatelessWidget {
12
this.formattedAmount,
13
@required this.onTap});
14
15
+ final VoidCallback onTap;
16
+ final ExchangeProviderDescription provider;
17
+ final CryptoCurrency from;
18
+ final CryptoCurrency to;
19
+ final String createdAtFormattedDate;
20
+ final String formattedAmount;
21
+
22
@override
23
Widget build(BuildContext context) {
24
final amountCrypto = provider == ExchangeProviderDescription.xmrto
@@ -48,7 +48,10 @@ class TradeRow extends StatelessWidget {
48
Text('${from.toString()} → ${to.toString()}',
49
style: TextStyle(
50
fontSize: 16,
51
- color: Theme.of(context).primaryTextTheme.subhead.color)),
51
+ color: Theme.of(context)
52
+ .primaryTextTheme
53
+ .subhead
54
+ .color)),
55
formattedAmount != null
56
? Text(formattedAmount + ' ' + amountCrypto,
57
style: const TextStyle(
lib/src/screens/dashboard/transaction_raw.dart
+11
-8
@@ -4,13 +4,6 @@ import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
4
import 'package:cake_wallet/generated/i18n.dart';
5
6
class TransactionRow extends StatelessWidget {
7
- final VoidCallback onTap;
8
- final TransactionDirection direction;
9
- final String formattedDate;
10
- final String formattedAmount;
11
- final String formattedFiatAmount;
12
- final bool isPending;
13
-
7
TransactionRow(
8
{this.direction,
9
this.formattedDate,
@@ -19,6 +12,13 @@ class TransactionRow extends StatelessWidget {
12
this.isPending,
13
@required this.onTap});
14
15
+ final VoidCallback onTap;
16
+ final TransactionDirection direction;
17
+ final String formattedDate;
18
+ final String formattedAmount;
19
+ final String formattedFiatAmount;
20
+ final bool isPending;
21
+
22
@override
23
Widget build(BuildContext context) {
24
return InkWell(
@@ -53,7 +53,10 @@ class TransactionRow extends StatelessWidget {
53
(isPending ? S.of(context).pending : ''),
54
style: TextStyle(
55
fontSize: 16,
56
- color: Theme.of(context).primaryTextTheme.subhead.color)),
56
+ color: Theme.of(context)
57
+ .primaryTextTheme
58
+ .subhead
59
+ .color)),
60
Text(formattedAmount,
61
style: const TextStyle(
62
fontSize: 16, color: Palette.purpleBlue))
lib/src/screens/dashboard/wallet_menu.dart
+9
-7
@@ -1,10 +1,13 @@
1
import 'package:flutter/material.dart';
2
import 'package:cake_wallet/routes.dart';
3
import 'package:provider/provider.dart';
4
-import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
4
import 'package:cake_wallet/generated/i18n.dart';
5
+import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
6
+import 'package:cake_wallet/src/screens/auth/auth_page.dart';
7
8
class WalletMenu {
9
+ WalletMenu(this.context);
10
+
11
final List<String> items = [
12
S.current.reconnect,
13
S.current.rescan,
@@ -14,9 +17,8 @@ class WalletMenu {
17
S.current.accounts,
18
S.current.address_book_menu
19
];
17
- final BuildContext context;
20
19
- WalletMenu(this.context);
21
+ final BuildContext context;
22
23
void action(int index) {
24
switch (index) {
@@ -32,7 +34,7 @@ class WalletMenu {
34
break;
35
case 3:
36
Navigator.of(context).pushNamed(Routes.auth,
35
- arguments: (isAuthenticatedSuccessfully, auth) =>
37
+ arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) =>
38
isAuthenticatedSuccessfully
39
? Navigator.of(auth.context).popAndPushNamed(Routes.seed)
40
: null);
@@ -40,7 +42,7 @@ class WalletMenu {
42
break;
43
case 4:
44
Navigator.of(context).pushNamed(Routes.auth,
43
- arguments: (isAuthenticatedSuccessfully, auth) =>
45
+ arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) =>
46
isAuthenticatedSuccessfully
47
? Navigator.of(auth.context)
48
.popAndPushNamed(Routes.showKeys)
@@ -57,10 +59,10 @@ class WalletMenu {
59
}
60
}
61
60
- Future _presentReconnectAlert(BuildContext context) async {
62
+ Future<void> _presentReconnectAlert(BuildContext context) async {
63
final walletStore = Provider.of<WalletStore>(context);
64
63
- await showDialog(
65
+ await showDialog<void>(
66
context: context,
67
builder: (BuildContext context) {
68
return AlertDialog(
lib/src/screens/disclaimer/disclaimer_page.dart
+36
-33
@@ -8,10 +8,10 @@ import 'package:cake_wallet/src/screens/base_page.dart';
8
import 'package:cake_wallet/src/widgets/primary_button.dart';
9
10
class DisclaimerPage extends BasePage {
11
- final bool isReadOnly;
12
-
11
DisclaimerPage({this.isReadOnly = false});
12
13
+ final bool isReadOnly;
14
+
15
@override
16
bool get isModalBackButton => false;
17
@@ -23,25 +23,25 @@ class DisclaimerPage extends BasePage {
23
}
24
25
class DisclaimerPageBody extends StatefulWidget {
26
- final bool isReadOnly;
27
-
26
DisclaimerPageBody({this.isReadOnly = true});
27
28
+ final bool isReadOnly;
29
+
30
@override
31
- createState() => DisclaimerBodyState(false);
31
+ DisclaimerBodyState createState() => DisclaimerBodyState(false);
32
}
33
34
class DisclaimerBodyState extends State<DisclaimerPageBody> {
35
- static const xmrto_url = 'https://xmr.to/app_static/html/tos.html';
36
- static const changenow_url = 'https://changenow.io/terms-of-use';
35
+ DisclaimerBodyState(this._isAccepted);
36
38
- bool _isAccepted;
37
+ static const xmrtoUrl = 'https://xmr.to/app_static/html/tos.html';
38
+ static const changenowUrl = 'https://changenow.io/terms-of-use';
39
+
40
+ final bool _isAccepted;
41
bool _checked = false;
42
String _fileText = '';
43
42
- DisclaimerBodyState(this._isAccepted);
43
-
44
- launchUrl(String url) async {
44
+ Future<void> launchUrl(String url) async {
45
if (await canLaunch(url)) await launch(url);
46
}
47
@@ -50,8 +50,8 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
50
setState(() {});
51
}
52
53
- _showAlertDialog(BuildContext context) async {
54
- await showDialog(
53
+ Future<void> _showAlertDialog(BuildContext context) async {
54
+ await showDialog<void>(
55
context: context,
56
builder: (BuildContext context) {
57
return AlertDialog(
@@ -66,7 +66,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
66
actions: <Widget>[
67
FlatButton(
68
onPressed: () {
69
- Navigator.pop(context);
69
+ Navigator.of(context).pop();
70
},
71
child: Text('OK')),
72
],
@@ -74,9 +74,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
74
});
75
}
76
77
- _afterLayout(_) {
78
- _showAlertDialog(context);
79
- }
77
+ void _afterLayout(Duration _) => _showAlertDialog(context);
78
79
@override
80
void initState() {
@@ -87,7 +85,6 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
85
86
@override
87
Widget build(BuildContext context) {
90
-
88
return Column(
89
children: <Widget>[
90
SizedBox(height: 10.0),
@@ -166,9 +163,9 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
163
children: <Widget>[
164
Expanded(
165
child: GestureDetector(
169
- onTap: () => launchUrl(xmrto_url),
166
+ onTap: () => launchUrl(xmrtoUrl),
167
child: Text(
171
- xmrto_url,
168
+ xmrtoUrl,
169
textAlign: TextAlign.left,
170
style: TextStyle(
171
color: Colors.blue,
@@ -187,17 +184,17 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
184
children: <Widget>[
185
Expanded(
186
child: GestureDetector(
190
- onTap: () => launchUrl(changenow_url),
191
- child: Text(
192
- changenow_url,
193
- textAlign: TextAlign.left,
194
- style: TextStyle(
195
- color: Colors.blue,
196
- fontSize: 14.0,
197
- fontWeight: FontWeight.normal,
198
- decoration: TextDecoration.underline),
199
- ),
200
- ))
187
+ onTap: () => launchUrl(changenowUrl),
188
+ child: Text(
189
+ changenowUrl,
190
+ textAlign: TextAlign.left,
191
+ style: TextStyle(
192
+ color: Colors.blue,
193
+ fontSize: 14.0,
194
+ fontWeight: FontWeight.normal,
195
+ decoration: TextDecoration.underline),
196
+ ),
197
+ ))
198
],
199
),
200
SizedBox(
@@ -288,8 +285,14 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
285
child: PrimaryButton(
286
onPressed: _checked ? () {} : null,
287
text: 'Accept',
291
- color: Theme.of(context).primaryTextTheme.button.backgroundColor,
292
- borderColor: Theme.of(context).primaryTextTheme.button.decorationColor,
288
+ color: Theme.of(context)
289
+ .primaryTextTheme
290
+ .button
291
+ .backgroundColor,
292
+ borderColor: Theme.of(context)
293
+ .primaryTextTheme
294
+ .button
295
+ .decorationColor,
296
),
297
)
298
: Offstage(),
lib/src/screens/exchange/exchange_page.dart
+26
-21
@@ -6,8 +6,9 @@ import 'package:provider/provider.dart';
6
import 'package:cake_wallet/palette.dart';
7
import 'package:cake_wallet/routes.dart';
8
import 'package:cake_wallet/generated/i18n.dart';
9
-import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
9
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
10
+import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
11
+import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
12
import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
13
import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
14
import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
@@ -20,15 +21,14 @@ import 'package:cake_wallet/src/widgets/picker.dart';
21
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
22
23
class ExchangePage extends BasePage {
24
+ @override
25
String get title => S.current.exchange;
26
27
@override
28
bool get isModalBackButton => true;
29
28
- final Image arrowBottomPurple = Image.asset(
29
- 'assets/images/arrow_bottom_purple_icon.png',
30
- height: 8,
31
- );
30
+ final Image arrowBottomPurple =
31
+ Image.asset('assets/images/arrow_bottom_purple_icon.png', height: 8);
32
33
@override
34
Widget middle(BuildContext context) {
@@ -93,12 +93,12 @@ class ExchangePage extends BasePage {
93
final items = exchangeStore.providersForCurrentPair();
94
final selectedItem = items.indexOf(exchangeStore.provider);
95
96
- showDialog(
96
+ showDialog<void>(
97
builder: (_) => Picker(
98
items: items,
99
selectedAtIndex: selectedItem,
100
title: S.of(context).change_exchange_provider,
101
- onItemSelected: (provider) =>
101
+ onItemSelected: (ExchangeProvider provider) =>
102
exchangeStore.changeProvider(provider: provider)),
103
context: context);
104
}
@@ -253,8 +253,9 @@ class ExchangeFormState extends State<ExchangeForm> {
253
builder: (_) => LoadingPrimaryButton(
254
text: S.of(context).exchange,
255
onPressed: () {
256
- if (_formKey.currentState.validate())
256
+ if (_formKey.currentState.validate()) {
257
exchangeStore.createTrade();
258
+ }
259
},
260
color: Theme.of(context)
261
.primaryTextTheme
@@ -327,34 +328,38 @@ class ExchangeFormState extends State<ExchangeForm> {
328
329
reaction(
330
(_) => walletStore.name,
330
- (_) => _onWalletNameChange(
331
+ (String _) => _onWalletNameChange(
332
walletStore, store.receiveCurrency, receiveKey));
333
334
reaction(
335
(_) => walletStore.name,
335
- (_) => _onWalletNameChange(
336
+ (String _) => _onWalletNameChange(
337
walletStore, store.depositCurrency, depositKey));
338
338
- reaction((_) => store.receiveCurrency,
339
- (currency) => _onCurrencyChange(currency, walletStore, receiveKey));
339
+ reaction(
340
+ (_) => store.receiveCurrency,
341
+ (CryptoCurrency currency) =>
342
+ _onCurrencyChange(currency, walletStore, receiveKey));
343
341
- reaction((_) => store.depositCurrency,
342
- (currency) => _onCurrencyChange(currency, walletStore, depositKey));
344
+ reaction(
345
+ (_) => store.depositCurrency,
346
+ (CryptoCurrency currency) =>
347
+ _onCurrencyChange(currency, walletStore, depositKey));
348
344
- reaction((_) => store.depositAmount, (amount) {
349
+ reaction((_) => store.depositAmount, (String amount) {
350
if (depositKey.currentState.amountController.text != amount) {
351
depositKey.currentState.amountController.text = amount;
352
}
353
});
354
350
- reaction((_) => store.receiveAmount, (amount) {
355
+ reaction((_) => store.receiveAmount, (String amount) {
356
if (receiveKey.currentState.amountController.text !=
357
store.receiveAmount) {
358
receiveKey.currentState.amountController.text = amount;
359
}
360
});
361
357
- reaction((_) => store.provider, (provider) {
362
+ reaction((_) => store.provider, (ExchangeProvider provider) {
363
final isReversed = provider is XMRTOExchangeProvider;
364
365
if (isReversed) {
@@ -373,10 +378,10 @@ class ExchangeFormState extends State<ExchangeForm> {
378
receiveKey.currentState.changeIsAmountEstimated(!isReversed);
379
});
380
376
- reaction((_) => store.tradeState, (state) {
381
+ reaction((_) => store.tradeState, (ExchangeTradeState state) {
382
if (state is TradeIsCreatedFailure) {
383
WidgetsBinding.instance.addPostFrameCallback((_) {
379
- showDialog(
384
+ showDialog<void>(
385
context: context,
386
builder: (BuildContext context) {
387
return AlertDialog(
@@ -397,7 +402,7 @@ class ExchangeFormState extends State<ExchangeForm> {
402
}
403
});
404
400
- reaction((_) => store.limitsState, (state) {
405
+ reaction((_) => store.limitsState, (LimitsState state) {
406
final isXMRTO = store.provider is XMRTOExchangeProvider;
407
String min;
408
String max;
@@ -444,7 +449,7 @@ class ExchangeFormState extends State<ExchangeForm> {
449
}
450
});
451
447
- reaction((_) => walletStore.address, (address) {
452
+ reaction((_) => walletStore.address, (String address) {
453
if (store.depositCurrency == CryptoCurrency.xmr) {
454
depositKey.currentState.changeAddress(address: address);
455
}
lib/src/screens/exchange/widgets/exchange_card.dart
+40
-27
@@ -7,18 +7,6 @@ import 'package:cake_wallet/src/widgets/picker.dart';
7
import 'package:cake_wallet/src/widgets/address_text_field.dart';
8
9
class ExchangeCard extends StatefulWidget {
10
- final List<CryptoCurrency> currencies;
11
- final Function(CryptoCurrency) onCurrencySelected;
12
- final CryptoCurrency initialCurrency;
13
- final String initialWalletName;
14
- final String initialAddress;
15
- final bool initialIsAmountEditable;
16
- final bool initialIsAddressEditable;
17
- final bool isAmountEstimated;
18
- final Image imageArrow;
19
- final FormFieldValidator<String> currencyValueValidator;
20
- final FormFieldValidator<String> addressTextFieldValidator;
21
-
10
ExchangeCard(
11
{Key key,
12
this.initialCurrency,
@@ -34,8 +22,20 @@ class ExchangeCard extends StatefulWidget {
22
this.addressTextFieldValidator})
23
: super(key: key);
24
25
+ final List<CryptoCurrency> currencies;
26
+ final Function(CryptoCurrency) onCurrencySelected;
27
+ final CryptoCurrency initialCurrency;
28
+ final String initialWalletName;
29
+ final String initialAddress;
30
+ final bool initialIsAmountEditable;
31
+ final bool initialIsAddressEditable;
32
+ final bool isAmountEstimated;
33
+ final Image imageArrow;
34
+ final FormFieldValidator<String> currencyValueValidator;
35
+ final FormFieldValidator<String> addressTextFieldValidator;
36
+
37
@override
38
- createState() => ExchangeCardState();
38
+ ExchangeCardState createState() => ExchangeCardState();
39
}
40
41
class ExchangeCardState extends State<ExchangeCard> {
@@ -102,7 +102,6 @@ class ExchangeCardState extends State<ExchangeCard> {
102
103
@override
104
Widget build(BuildContext context) {
105
-
105
return Container(
106
padding: EdgeInsets.fromLTRB(22, 15, 22, 30),
107
width: double.infinity,
@@ -150,7 +149,10 @@ class ExchangeCardState extends State<ExchangeCard> {
149
style: TextStyle(
150
fontWeight: FontWeight.bold,
151
fontSize: 24,
153
- color: Theme.of(context).primaryTextTheme.title.color)),
152
+ color: Theme.of(context)
153
+ .primaryTextTheme
154
+ .title
155
+ .color)),
156
widget.imageArrow
157
]),
158
_walletName != null
@@ -173,7 +175,10 @@ class ExchangeCardState extends State<ExchangeCard> {
175
textAlign: TextAlign.right,
176
keyboardType: TextInputType.numberWithOptions(
177
signed: false, decimal: false),
176
- inputFormatters: [BlacklistingTextInputFormatter(new RegExp('[\\-|\\ |\\,]'))],
178
+ inputFormatters: [
179
+ BlacklistingTextInputFormatter(
180
+ RegExp('[\\-|\\ |\\,]'))
181
+ ],
182
decoration: InputDecoration(
183
hintStyle: TextStyle(
184
color: Theme.of(context).cardTheme.color,
@@ -182,15 +187,14 @@ class ExchangeCardState extends State<ExchangeCard> {
187
hintText: '0.00000000',
188
focusedBorder: UnderlineInputBorder(
189
borderSide: BorderSide(
185
- color: Palette.cakeGreen,
186
- width: 2.0)),
190
+ color: Palette.cakeGreen, width: 2.0)),
191
enabledBorder: UnderlineInputBorder(
192
borderSide: BorderSide(
193
color: _isAmountEditable
194
? Palette.deepPurple
195
: Theme.of(context).focusColor,
196
width: 1.0))),
193
- validator: widget.currencyValueValidator),
197
+ validator: widget.currencyValueValidator),
198
SizedBox(height: 5),
199
SizedBox(
200
height: 15,
@@ -201,21 +205,29 @@ class ExchangeCardState extends State<ExchangeCard> {
205
children: <Widget>[
206
_min != null
207
? Text(
204
- S.of(context).min_value(_min, _selectedCurrency.toString()),
208
+ S.of(context).min_value(
209
+ _min, _selectedCurrency.toString()),
210
style: TextStyle(
211
fontSize: 10,
212
height: 1.2,
208
- color: Theme.of(context).primaryTextTheme.subtitle.color),
213
+ color: Theme.of(context)
214
+ .primaryTextTheme
215
+ .subtitle
216
+ .color),
217
)
218
: SizedBox(),
219
_min != null ? SizedBox(width: 10) : SizedBox(),
220
_max != null
221
? Text(
214
- S.of(context).max_value(_max, _selectedCurrency.toString()),
222
+ S.of(context).max_value(
223
+ _max, _selectedCurrency.toString()),
224
style: TextStyle(
225
fontSize: 10,
226
height: 1.2,
218
- color: Theme.of(context).primaryTextTheme.subtitle.color))
227
+ color: Theme.of(context)
228
+ .primaryTextTheme
229
+ .subtitle
230
+ .color))
231
: SizedBox(),
232
]),
233
),
@@ -248,14 +260,15 @@ class ExchangeCardState extends State<ExchangeCard> {
260
}
261
262
void _presentPicker(BuildContext context) {
251
- showDialog(
263
+ showDialog<void>(
264
builder: (_) => Picker(
265
items: widget.currencies,
266
selectedAtIndex: widget.currencies.indexOf(_selectedCurrency),
267
title: S.of(context).change_currency,
256
- onItemSelected: (item) => widget.onCurrencySelected != null
257
- ? widget.onCurrencySelected(item)
258
- : null),
268
+ onItemSelected: (CryptoCurrency item) =>
269
+ widget.onCurrencySelected != null
270
+ ? widget.onCurrencySelected(item)
271
+ : null),
272
context: context);
273
}
274
}
lib/src/screens/exchange_trade/exchange_confirm_page.dart
+3
-2
@@ -8,11 +8,12 @@ import 'package:cake_wallet/src/screens/base_page.dart';
8
import 'package:cake_wallet/src/domain/exchange/trade.dart';
9
10
class ExchangeConfirmPage extends BasePage {
11
- String get title => S.current.copy_id;
11
+ ExchangeConfirmPage({@required this.trade});
12
13
final Trade trade;
14
15
- ExchangeConfirmPage({@required this.trade});
15
+ @override
16
+ String get title => S.current.copy_id;
17
18
@override
19
Widget body(BuildContext context) {
lib/src/screens/exchange_trade/exchange_trade_page.dart
+5
-4
@@ -20,6 +20,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
20
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
21
22
class ExchangeTradePage extends BasePage {
23
+ @override
24
String get title => S.current.exchange;
25
26
@override
@@ -28,7 +29,7 @@ class ExchangeTradePage extends BasePage {
29
30
class ExchangeTradeForm extends StatefulWidget {
31
@override
31
- createState() => ExchangeTradeState();
32
+ ExchangeTradeState createState() => ExchangeTradeState();
33
}
34
35
class ExchangeTradeState extends State<ExchangeTradeForm> {
@@ -330,10 +331,10 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
331
332
final sendStore = Provider.of<SendStore>(context);
333
333
- reaction((_) => sendStore.state, (state) {
334
+ reaction((_) => sendStore.state, (SendingState state) {
335
if (state is SendingFailed) {
336
WidgetsBinding.instance.addPostFrameCallback((_) {
336
- showDialog(
337
+ showDialog<void>(
338
context: context,
339
builder: (BuildContext context) {
340
return AlertDialog(
@@ -351,7 +352,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
352
353
if (state is TransactionCreatedSuccessfully) {
354
WidgetsBinding.instance.addPostFrameCallback((_) {
354
- showDialog(
355
+ showDialog<void>(
356
context: context,
357
builder: (BuildContext context) {
358
return AlertDialog(
lib/src/screens/exchange_trade/widgets/copy_button.dart
+16
-16
@@ -2,29 +2,29 @@ import 'package:flutter/cupertino.dart';
2
import 'package:flutter/material.dart';
3
4
class CopyButton extends StatelessWidget {
5
+ const CopyButton(
6
+ {@required this.onPressed,
7
+ @required this.text,
8
+ @required this.color,
9
+ @required this.borderColor});
10
11
final VoidCallback onPressed;
12
final Color color;
13
final Color borderColor;
14
final String text;
15
11
- const CopyButton({
12
- @required this.onPressed,
13
- @required this.text,
14
- @required this.color,
15
- @required this.borderColor});
16
-
16
@override
17
Widget build(BuildContext context) {
18
return ButtonTheme(
20
- minWidth: double.infinity,
21
- height: 44.0,
22
- child: FlatButton(
23
- onPressed: onPressed,
24
- color: color,
25
- shape: RoundedRectangleBorder(side: BorderSide(color: borderColor), borderRadius: BorderRadius.circular(10.0)),
26
- child: Text(text, style: TextStyle(fontSize: 14.0)),
27
- )
28
- );
19
+ minWidth: double.infinity,
20
+ height: 44.0,
21
+ child: FlatButton(
22
+ onPressed: onPressed,
23
+ color: color,
24
+ shape: RoundedRectangleBorder(
25
+ side: BorderSide(color: borderColor),
26
+ borderRadius: BorderRadius.circular(10.0)),
27
+ child: Text(text, style: TextStyle(fontSize: 14.0)),
28
+ ));
29
}
30
-}
\ No newline at end of file
30
+}
lib/src/screens/exchange_trade/widgets/timer_widget.dart
+7
-6
@@ -3,24 +3,24 @@ import 'dart:async';
3
import 'package:cake_wallet/generated/i18n.dart';
4
5
class TimerWidget extends StatefulWidget {
6
+ TimerWidget(this.expiratedAt, {this.color = Colors.black});
7
+
8
final DateTime expiratedAt;
9
final Color color;
10
9
- TimerWidget(this.expiratedAt, {this.color = Colors.black});
10
-
11
@override
12
- createState() => TimerWidgetState();
12
+ TimerWidgetState createState() => TimerWidgetState();
13
}
14
15
class TimerWidgetState extends State<TimerWidget> {
16
+ TimerWidgetState();
17
+
18
int _leftSeconds;
19
int _minutes;
20
int _seconds;
21
bool _isExpired;
22
Timer _timer;
23
22
- TimerWidgetState();
23
-
24
@override
25
void initState() {
26
super.initState();
@@ -52,7 +52,8 @@ class TimerWidgetState extends State<TimerWidget> {
52
@override
53
Widget build(BuildContext context) {
54
return _isExpired
55
- ? Text(S.of(context).expired, style: TextStyle(fontSize: 14.0, color: Colors.red))
55
+ ? Text(S.of(context).expired,
56
+ style: TextStyle(fontSize: 14.0, color: Colors.red))
57
: Text(
58
S.of(context).time(_minutes.toString(), _seconds.toString()),
59
style: TextStyle(fontSize: 14.0, color: widget.color),
lib/src/screens/faq/faq_page.dart
+12
-21
@@ -7,14 +7,16 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart';
7
import 'package:cake_wallet/src/screens/base_page.dart';
8
9
class FaqPage extends BasePage {
10
+ @override
11
String get title => S.current.faq;
12
13
@override
14
Widget body(BuildContext context) {
14
-
15
return FutureBuilder(
16
builder: (context, snapshot) {
17
- var faqItems = json.decode(snapshot.data.toString());
17
+ final faqItems = (json.decode(snapshot.data.toString())
18
+ as List<Map<String, String>>) ??
19
+ <Map<String, String>>[];
20
21
return ListView.separated(
22
itemBuilder: (BuildContext context, int index) {
@@ -22,34 +24,24 @@ class FaqPage extends BasePage {
24
final itemChild = faqItems[index]["answer"];
25
26
return ExpansionTile(
25
- title: Text(
26
- itemTitle
27
- ),
27
+ title: Text(itemTitle),
28
children: <Widget>[
29
Row(
30
mainAxisAlignment: MainAxisAlignment.start,
31
children: <Widget>[
32
Expanded(
33
child: Container(
34
- padding: EdgeInsets.only(
35
- left: 15.0,
36
- right: 15.0
37
- ),
38
- child: Text(
39
- itemChild,
40
- ),
41
- )
42
- )
34
+ padding: EdgeInsets.only(left: 15.0, right: 15.0),
35
+ child: Text(itemChild),
36
+ ))
37
],
38
)
39
],
40
);
41
},
48
- separatorBuilder: (_, __) => Divider(
49
- color: Theme.of(context).dividerTheme.color,
50
- height: 1.0,
51
- ),
52
- itemCount: faqItems == null ? 0 : faqItems.length,
42
+ separatorBuilder: (_, __) =>
43
+ Divider(color: Theme.of(context).dividerTheme.color, height: 1.0),
44
+ itemCount: faqItems.length,
45
);
46
},
47
future: rootBundle.loadString(getFaqPath(context)),
@@ -86,5 +78,4 @@ class FaqPage extends BasePage {
78
return 'assets/faq/faq_en.json';
79
}
80
}
89
-
90
-}
\ No newline at end of file
81
+}
lib/src/screens/new_wallet/new_wallet_page.dart
+11
-10
@@ -15,24 +15,25 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
15
import 'package:cake_wallet/palette.dart';
16
17
class NewWalletPage extends BasePage {
18
+ NewWalletPage(
19
+ {@required this.walletsService,
20
+ @required this.walletService,
21
+ @required this.sharedPreferences});
22
+
23
final WalletListService walletsService;
24
final WalletService walletService;
25
final SharedPreferences sharedPreferences;
26
27
+ @override
28
String get title => S.current.new_wallet;
29
24
- NewWalletPage(
25
- {@required this.walletsService,
26
- @required this.walletService,
27
- @required this.sharedPreferences});
28
-
30
@override
31
Widget body(BuildContext context) => WalletNameForm();
32
}
33
34
class WalletNameForm extends StatefulWidget {
35
@override
35
- createState() => _WalletNameFormState();
36
+ _WalletNameFormState createState() => _WalletNameFormState();
37
}
38
39
class _WalletNameFormState extends State<WalletNameForm> {
@@ -43,14 +44,14 @@ class _WalletNameFormState extends State<WalletNameForm> {
44
Widget build(BuildContext context) {
45
final walletCreationStore = Provider.of<WalletCreationStore>(context);
46
46
- reaction((_) => walletCreationStore.state, (state) {
47
+ reaction((_) => walletCreationStore.state, (WalletCreationState state) {
48
if (state is WalletCreatedSuccessfully) {
49
Navigator.of(context).popUntil((route) => route.isFirst);
50
}
51
52
if (state is WalletCreationFailure) {
53
WidgetsBinding.instance.addPostFrameCallback((_) {
53
- showDialog(
54
+ showDialog<void>(
55
context: context,
56
builder: (BuildContext context) {
57
return AlertDialog(
@@ -88,8 +89,8 @@ class _WalletNameFormState extends State<WalletNameForm> {
89
fontSize: 24.0, color: Theme.of(context).hintColor),
90
hintText: S.of(context).wallet_name,
91
focusedBorder: UnderlineInputBorder(
91
- borderSide: BorderSide(
92
- color: Palette.cakeGreen, width: 2.0)),
92
+ borderSide:
93
+ BorderSide(color: Palette.cakeGreen, width: 2.0)),
94
enabledBorder: UnderlineInputBorder(
95
borderSide: BorderSide(
96
color: Theme.of(context).focusColor,
lib/src/screens/nodes/new_node_page.dart
+1
-1
@@ -17,7 +17,7 @@ class NewNodePage extends BasePage {
17
18
class NewNodePageForm extends StatefulWidget {
19
@override
20
- createState() => NewNodeFormState();
20
+ NewNodeFormState createState() => NewNodeFormState();
21
}
22
23
class NewNodeFormState extends State<NewNodePageForm> {
lib/src/screens/nodes/node_indicator.dart
+4
-6
@@ -2,18 +2,16 @@ import 'package:flutter/material.dart';
2
import 'package:cake_wallet/palette.dart';
3
4
class NodeIndicator extends StatelessWidget {
5
- final color;
6
-
5
NodeIndicator({this.color = Palette.red});
6
7
+ final Color color;
8
+
9
@override
10
Widget build(BuildContext context) {
11
return Container(
12
width: 10.0,
13
height: 10.0,
14
- decoration: BoxDecoration(
15
- shape: BoxShape.circle,
16
- color: color),
14
+ decoration: BoxDecoration(shape: BoxShape.circle, color: color),
15
);
16
}
19
-}
\ No newline at end of file
17
+}
lib/src/screens/nodes/nodes_list_page.dart
+7
-8
@@ -13,6 +13,7 @@ import 'package:cake_wallet/src/screens/base_page.dart';
13
class NodeListPage extends BasePage {
14
NodeListPage();
15
16
+ @override
17
String get title => S.current.nodes;
18
19
@override
@@ -26,7 +27,7 @@ class NodeListPage extends BasePage {
27
minWidth: double.minPositive,
28
child: FlatButton(
29
onPressed: () async {
29
- await showDialog(
30
+ await showDialog<void>(
31
context: context,
32
builder: (BuildContext context) {
33
return AlertDialog(
@@ -76,10 +77,8 @@ class NodeListPage extends BasePage {
77
height: 28.0,
78
child: FlatButton(
79
shape: CircleBorder(),
79
- onPressed: () async {
80
- await Navigator.of(context).pushNamed(Routes.newNode);
81
- nodeList.update();
82
- },
80
+ onPressed: () async =>
81
+ await Navigator.of(context).pushNamed(Routes.newNode),
82
child: Offstage()),
83
)
84
],
@@ -94,7 +93,7 @@ class NodeListPage extends BasePage {
93
94
class NodeListPageBody extends StatefulWidget {
95
@override
97
- createState() => NodeListPageBodyState();
96
+ NodeListPageBodyState createState() => NodeListPageBodyState();
97
}
98
99
class NodeListPageBodyState extends State<NodeListPageBody> {
@@ -141,7 +140,7 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
140
switch (snapshot.connectionState) {
141
case ConnectionState.done:
142
return NodeIndicator(
144
- color: snapshot.data
143
+ color: snapshot.data as bool
144
? Palette.green
145
: Palette.red);
146
default:
@@ -150,7 +149,7 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
149
}),
150
onTap: () async {
151
if (!isCurrent) {
153
- await showDialog(
152
+ await showDialog<void>(
153
context: context,
154
builder: (BuildContext context) {
155
return AlertDialog(
lib/src/screens/pin_code/pin_code.dart
+33
-33
@@ -6,19 +6,20 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart';
6
import 'package:cake_wallet/generated/i18n.dart';
7
8
abstract class PinCodeWidget extends StatefulWidget {
9
- final Function(List<int> pin, PinCodeState state) onPinCodeEntered;
10
- final bool hasLengthSwitcher;
11
-
9
PinCodeWidget({Key key, this.onPinCodeEntered, this.hasLengthSwitcher})
10
: super(key: key);
14
-}
11
16
-class PinCode extends PinCodeWidget {
12
final Function(List<int> pin, PinCodeState state) onPinCodeEntered;
13
final bool hasLengthSwitcher;
14
+}
15
20
- PinCode(this.onPinCodeEntered, this.hasLengthSwitcher, Key key)
21
- : super(key: key);
16
+class PinCode extends PinCodeWidget {
17
+ PinCode(Function(List<int> pin, PinCodeState state) onPinCodeEntered,
18
+ bool hasLengthSwitcher, Key key)
19
+ : super(
20
+ key: key,
21
+ onPinCodeEntered: onPinCodeEntered,
22
+ hasLengthSwitcher: hasLengthSwitcher);
23
24
@override
25
PinCodeState createState() => PinCodeState();
@@ -30,27 +31,22 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
31
static const fourPinLength = 4;
32
static final deleteIconImage = Image.asset('assets/images/delete_icon.png');
33
static final backArrowImage = Image.asset('assets/images/back_arrow.png');
33
- GlobalKey _gridViewKey = GlobalKey();
34
+ final _gridViewKey = GlobalKey();
35
36
int pinLength = defaultPinLength;
37
List<int> pin = List<int>.filled(defaultPinLength, null);
38
String title = S.current.enter_your_pin;
39
double _aspectRatio = 0;
40
40
- void setTitle(String title) {
41
- setState(() => this.title = title);
42
- }
41
+ void setTitle(String title) => setState(() => this.title = title);
42
44
- void clear() {
45
- setState(() => pin = List<int>.filled(pinLength, null));
46
- }
43
+ void clear() => setState(() => pin = List<int>.filled(pinLength, null));
44
48
- void onPinCodeEntered(PinCodeState state) {
49
- widget.onPinCodeEntered(state.pin, this);
50
- }
45
+ void onPinCodeEntered(PinCodeState state) =>
46
+ widget.onPinCodeEntered(state.pin, this);
47
48
void changePinLength(int length) {
53
- List<int> newPin = List<int>.filled(length, null);
49
+ final newPin = List<int>.filled(length, null);
50
51
setState(() {
52
pinLength = length;
@@ -58,19 +54,23 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
54
});
55
}
56
61
- setDefaultPinLength() {
57
+ void setDefaultPinLength() {
58
final settingsStore = Provider.of<SettingsStore>(context);
59
60
pinLength = settingsStore.defaultPinLength;
61
changePinLength(pinLength);
62
}
63
68
- getCurrentAspectRatio() {
69
- final RenderBox renderBox = _gridViewKey.currentContext.findRenderObject();
64
+ void calculateAspectRatio() {
65
+ final renderBox =
66
+ _gridViewKey.currentContext.findRenderObject() as RenderBox;
67
+ final cellWidth = renderBox.size.width / 3;
68
+ final cellHeight = renderBox.size.height / 4;
69
+
70
+ if (cellWidth > 0 && cellHeight > 0) {
71
+ _aspectRatio = cellWidth / cellHeight;
72
+ }
73
71
- double cellWidth = renderBox.size.width / 3;
72
- double cellHeight = renderBox.size.height / 4;
73
- if (cellWidth > 0 && cellHeight > 0) _aspectRatio = cellWidth / cellHeight;
74
setState(() {});
75
}
76
@@ -80,15 +80,13 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
80
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
81
}
82
83
- afterLayout(_) {
83
+ void afterLayout(dynamic _) {
84
setDefaultPinLength();
85
- getCurrentAspectRatio();
85
+ calculateAspectRatio();
86
}
87
88
@override
89
- Widget build(BuildContext context) {
90
- return Scaffold(body: body(context));
91
- }
89
+ Widget build(BuildContext context) => Scaffold(body: body(context));
90
91
Widget body(BuildContext context) {
92
return SafeArea(
@@ -196,7 +194,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
194
}
195
196
void _push(int num) {
199
- if (_pinLength() >= pinLength) {
197
+ if (currentPinLength() >= pinLength) {
198
return;
199
}
200
@@ -207,13 +205,15 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
205
}
206
}
207
210
- if (_pinLength() == pinLength) {
208
+ final _currentPinLength = currentPinLength();
209
+
210
+ if (_currentPinLength == pinLength) {
211
onPinCodeEntered(this);
212
}
213
}
214
215
void _pop() {
216
- if (_pinLength() == 0) {
216
+ if (currentPinLength() == 0) {
217
return;
218
}
219
@@ -225,7 +225,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
225
}
226
}
227
228
- int _pinLength() {
228
+ int currentPinLength() {
229
return pin.fold(0, (v, e) {
230
if (e != null) {
231
return v + 1;
lib/src/screens/receive/qr_image.dart
+2
-2
@@ -10,7 +10,7 @@ class QrImage extends StatelessWidget {
10
Color foregroundColor = Colors.black,
11
int version = 7,
12
int errorCorrectionLevel = QrErrorCorrectLevel.L,
13
- }) : _painter = new QrPainter(data, foregroundColor, version, errorCorrectionLevel);
13
+ }) : _painter = QrPainter(data, foregroundColor, version, errorCorrectionLevel);
14
15
final QrPainter _painter;
16
final Color backgroundColor;
@@ -18,7 +18,7 @@ class QrImage extends StatelessWidget {
18
19
@override
20
Widget build(BuildContext context) {
21
- return new Container(
21
+ return Container(
22
width: size,
23
height: size,
24
color: backgroundColor,
lib/src/screens/receive/qr_painter.dart
+14
-11
@@ -3,31 +3,32 @@ import 'package:qr/qr.dart';
3
4
class QrPainter extends CustomPainter {
5
QrPainter(
6
- String data,
7
- this.color,
8
- this.version,
9
- this.errorCorrectionLevel,
10
- ) : this._qr = new QrCode(version, errorCorrectionLevel) {
6
+ String data,
7
+ this.color,
8
+ this.version,
9
+ this.errorCorrectionLevel,
10
+ ) : this._qr = QrCode(version, errorCorrectionLevel) {
11
_p.color = this.color;
12
13
_qr.addData(data);
14
_qr.make();
15
}
16
17
- final QrCode _qr;
18
- final _p = new Paint()..style = PaintingStyle.fill;
19
-
17
final int version;
18
final int errorCorrectionLevel;
19
final Color color;
20
21
+ final QrCode _qr;
22
+ final _p = Paint()..style = PaintingStyle.fill;
23
+
24
@override
25
void paint(Canvas canvas, Size size) {
26
final squareSize = size.shortestSide / _qr.moduleCount;
27
for (int x = 0; x < _qr.moduleCount; x++) {
28
for (int y = 0; y < _qr.moduleCount; y++) {
29
if (_qr.isDark(y, x)) {
30
- final squareRect = new Rect.fromLTWH(x * squareSize, y * squareSize, squareSize, squareSize);
30
+ final squareRect = Rect.fromLTWH(
31
+ x * squareSize, y * squareSize, squareSize, squareSize);
32
canvas.drawRect(squareRect, _p);
33
}
34
}
@@ -37,9 +38,11 @@ class QrPainter extends CustomPainter {
38
@override
39
bool shouldRepaint(CustomPainter oldDelegate) {
40
if (oldDelegate is QrPainter) {
40
- return this.color != oldDelegate.color || this.errorCorrectionLevel != oldDelegate.errorCorrectionLevel ||
41
+ return this.color != oldDelegate.color ||
42
+ this.errorCorrectionLevel != oldDelegate.errorCorrectionLevel ||
43
this.version != oldDelegate.version;
44
}
45
+
46
return false;
47
}
45
-}
\ No newline at end of file
48
+}
lib/src/screens/receive/receive_page.dart
+12
-6
@@ -13,7 +13,10 @@ import 'package:cake_wallet/src/screens/receive/qr_image.dart';
13
import 'package:cake_wallet/src/screens/base_page.dart';
14
15
class ReceivePage extends BasePage {
16
+ @override
17
bool get isModalBackButton => true;
18
+
19
+ @override
20
String get title => S.current.receive;
21
22
@override
@@ -31,7 +34,10 @@ class ReceivePage extends BasePage {
34
padding: EdgeInsets.all(0),
35
onPressed: () => Share.text(
36
'Share address', walletStore.subaddress.address, 'text/plain'),
34
- child: Icon(Icons.share, size: 30.0,)),
37
+ child: Icon(
38
+ Icons.share,
39
+ size: 30.0,
40
+ )),
41
),
42
);
43
}
@@ -43,7 +49,7 @@ class ReceivePage extends BasePage {
49
50
class ReceiveBody extends StatefulWidget {
51
@override
46
- createState() => ReceiveBodyState();
52
+ ReceiveBodyState createState() => ReceiveBodyState();
53
}
54
55
class ReceiveBodyState extends State<ReceiveBody> {
@@ -67,8 +73,9 @@ class ReceiveBodyState extends State<ReceiveBody> {
73
amountController.addListener(() {
74
if (_formKey.currentState.validate()) {
75
walletStore.onChangedAmountValue(amountController.text);
70
- } else
76
+ } else {
77
walletStore.onChangedAmountValue('');
78
+ }
79
});
80
81
return SafeArea(
@@ -152,7 +159,7 @@ class ReceiveBodyState extends State<ReceiveBody> {
159
TextInputType.numberWithOptions(decimal: true),
160
inputFormatters: [
161
BlacklistingTextInputFormatter(
155
- new RegExp('[\\-|\\ |\\,]'))
162
+ RegExp('[\\-|\\ |\\,]'))
163
],
164
style: TextStyle(
165
fontSize: 14.0,
@@ -163,8 +170,7 @@ class ReceiveBodyState extends State<ReceiveBody> {
170
hintText: S.of(context).amount,
171
focusedBorder: UnderlineInputBorder(
172
borderSide: BorderSide(
166
- color: Palette.cakeGreen,
167
- width: 2.0)),
173
+ color: Palette.cakeGreen, width: 2.0)),
174
enabledBorder: UnderlineInputBorder(
175
borderSide: BorderSide(
176
color: Theme.of(context).focusColor,
lib/src/screens/restore/restore_options_page.dart
+5
-1
@@ -9,7 +9,10 @@ import 'package:cake_wallet/generated/i18n.dart';
9
class RestoreOptionsPage extends BasePage {
10
static const _aspectRatioImage = 2.086;
11
12
+ @override
13
String get title => S.current.restore_restore_wallet;
14
+
15
+ @override
16
Color get backgroundColor => Palette.creamyGrey;
17
18
final _imageSeedKeys = Image.asset('assets/images/seedKeys.png');
@@ -26,7 +29,8 @@ class RestoreOptionsPage extends BasePage {
29
Flexible(
30
child: RestoreButton(
31
onPressed: () {
29
- Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome);
32
+ Navigator.pushNamed(
33
+ context, Routes.restoreWalletOptionsFromWelcome);
34
},
35
image: _imageSeedKeys,
36
aspectRatioImage: _aspectRatioImage,
lib/src/screens/restore/restore_wallet_from_keys_page.dart
+13
-16
@@ -17,24 +17,25 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
17
import 'package:cake_wallet/palette.dart';
18
19
class RestoreWalletFromKeysPage extends BasePage {
20
+ RestoreWalletFromKeysPage(
21
+ {@required this.walletsService,
22
+ @required this.sharedPreferences,
23
+ @required this.walletService});
24
+
25
final WalletListService walletsService;
26
final WalletService walletService;
27
final SharedPreferences sharedPreferences;
28
29
+ @override
30
String get title => S.current.restore_title_from_keys;
31
26
- RestoreWalletFromKeysPage(
27
- {@required this.walletsService,
28
- @required this.sharedPreferences,
29
- @required this.walletService});
30
-
32
@override
33
Widget body(BuildContext context) => RestoreFromKeysFrom();
34
}
35
36
class RestoreFromKeysFrom extends StatefulWidget {
37
@override
37
- createState() => _RestoreFromKeysFromState();
38
+ _RestoreFromKeysFromState createState() => _RestoreFromKeysFromState();
39
}
40
41
class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
@@ -49,14 +50,14 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
50
Widget build(BuildContext context) {
51
final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
52
52
- reaction((_) => walletRestorationStore.state, (state) {
53
+ reaction((_) => walletRestorationStore.state, (WalletRestorationState state) {
54
if (state is WalletRestoredSuccessfully) {
55
Navigator.of(context).popUntil((route) => route.isFirst);
56
}
57
58
if (state is WalletRestorationFailure) {
59
WidgetsBinding.instance.addPostFrameCallback((_) {
59
- showDialog(
60
+ showDialog<void>(
61
context: context,
62
builder: (BuildContext context) {
63
return AlertDialog(
@@ -97,8 +98,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
98
hintText: S.of(context).restore_wallet_name,
99
focusedBorder: UnderlineInputBorder(
100
borderSide: BorderSide(
100
- color: Palette.cakeGreen,
101
- width: 2.0)),
101
+ color: Palette.cakeGreen, width: 2.0)),
102
enabledBorder: UnderlineInputBorder(
103
borderSide: BorderSide(
104
color: Theme.of(context).focusColor,
@@ -127,8 +127,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
127
hintText: S.of(context).restore_address,
128
focusedBorder: UnderlineInputBorder(
129
borderSide: BorderSide(
130
- color: Palette.cakeGreen,
131
- width: 2.0)),
130
+ color: Palette.cakeGreen, width: 2.0)),
131
enabledBorder: UnderlineInputBorder(
132
borderSide: BorderSide(
133
color: Theme.of(context).focusColor,
@@ -155,8 +154,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
154
hintText: S.of(context).restore_view_key_private,
155
focusedBorder: UnderlineInputBorder(
156
borderSide: BorderSide(
158
- color: Palette.cakeGreen,
159
- width: 2.0)),
157
+ color: Palette.cakeGreen, width: 2.0)),
158
enabledBorder: UnderlineInputBorder(
159
borderSide: BorderSide(
160
color: Theme.of(context).focusColor,
@@ -183,8 +181,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
181
hintText: S.of(context).restore_spend_key_private,
182
focusedBorder: UnderlineInputBorder(
183
borderSide: BorderSide(
186
- color: Palette.cakeGreen,
187
- width: 2.0)),
184
+ color: Palette.cakeGreen, width: 2.0)),
185
enabledBorder: UnderlineInputBorder(
186
borderSide: BorderSide(
187
color: Theme.of(context).focusColor,
lib/src/screens/restore/restore_wallet_from_seed_details.dart
+5
-3
@@ -13,6 +13,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
13
import 'package:cake_wallet/palette.dart';
14
15
class RestoreWalletFromSeedDetailsPage extends BasePage {
16
+ @override
17
String get title => S.current.restore_wallet_restore_description;
18
19
@override
@@ -21,7 +22,8 @@ class RestoreWalletFromSeedDetailsPage extends BasePage {
22
23
class RestoreFromSeedDetailsForm extends StatefulWidget {
24
@override
24
- createState() => _RestoreFromSeedDetailsFormState();
25
+ _RestoreFromSeedDetailsFormState createState() =>
26
+ _RestoreFromSeedDetailsFormState();
27
}
28
29
class _RestoreFromSeedDetailsFormState
@@ -34,14 +36,14 @@ class _RestoreFromSeedDetailsFormState
36
Widget build(BuildContext context) {
37
final walletRestorationStore = Provider.of<WalletRestorationStore>(context);
38
37
- reaction((_) => walletRestorationStore.state, (state) {
39
+ reaction((_) => walletRestorationStore.state, (WalletRestorationState state) {
40
if (state is WalletRestoredSuccessfully) {
41
Navigator.of(context).popUntil((route) => route.isFirst);
42
}
43
44
if (state is WalletRestorationFailure) {
45
WidgetsBinding.instance.addPostFrameCallback((_) {
44
- showDialog(
46
+ showDialog<void>(
47
context: context,
48
builder: (BuildContext context) {
49
return AlertDialog(
lib/src/screens/restore/restore_wallet_from_seed_page.dart
+10
-10
@@ -14,24 +14,25 @@ import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_sto
14
import 'package:cake_wallet/src/widgets/seed_widget.dart';
15
16
class RestoreWalletFromSeedPage extends BasePage {
17
+ RestoreWalletFromSeedPage(
18
+ {@required this.walletsService,
19
+ @required this.walletService,
20
+ @required this.sharedPreferences});
21
+
22
final WalletListService walletsService;
23
final WalletService walletService;
24
final SharedPreferences sharedPreferences;
25
26
+ @override
27
String get title => S.current.restore_title_from_seed;
28
23
- RestoreWalletFromSeedPage(
24
- {@required this.walletsService,
25
- @required this.walletService,
26
- @required this.sharedPreferences});
27
-
29
@override
30
Widget body(BuildContext context) => RestoreFromSeedForm();
31
}
32
33
class RestoreFromSeedForm extends StatefulWidget {
34
@override
34
- createState() => _RestoreFromSeedFormState();
35
+ _RestoreFromSeedFormState createState() => _RestoreFromSeedFormState();
36
}
37
38
class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
@@ -46,9 +47,8 @@ class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
47
(_) => _setReactions(context, walletRestorationStore));
48
49
return GestureDetector(
49
- onTap: () {
50
- SystemChannels.textInput.invokeMethod('TextInput.hide');
51
- },
50
+ onTap: () =>
51
+ SystemChannels.textInput.invokeMethod<void>('TextInput.hide'),
52
child: Container(
53
padding: EdgeInsets.only(left: 20.0, right: 20.0, bottom: 20.0),
54
child: Column(
@@ -90,7 +90,7 @@ class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
90
return;
91
}
92
93
- reaction((_) => store.errorMessage, (errorMessage) {
93
+ reaction((_) => store.errorMessage, (String errorMessage) {
94
if (errorMessage == null || errorMessage.isEmpty) {
95
_seedKey.currentState.validated();
96
} else {
lib/src/screens/restore/restore_wallet_options_page.dart
+7
-4
@@ -9,7 +9,10 @@ import 'package:cake_wallet/generated/i18n.dart';
9
class RestoreWalletOptionsPage extends BasePage {
10
static const _aspectRatioImage = 2.086;
11
12
+ @override
13
String get title => S.current.restore_seed_keys_restore;
14
+
15
+ @override
16
Color get backgroundColor => Palette.creamyGrey;
17
18
final _imageSeed = Image.asset('assets/images/seedIco.png');
@@ -29,8 +32,8 @@ class RestoreWalletOptionsPage extends BasePage {
32
Navigator.pushNamed(context, Routes.restoreWalletFromSeed),
33
image: _imageSeed,
34
aspectRatioImage: _aspectRatioImage,
32
- titleColor: Palette.lightViolet,
33
- color: Palette.lightViolet,
35
+ titleColor: Palette.lightViolet,
36
+ color: Palette.lightViolet,
37
title: S.of(context).restore_title_from_seed,
38
description: S.of(context).restore_description_from_seed,
39
textButton: S.of(context).restore_next,
@@ -41,8 +44,8 @@ class RestoreWalletOptionsPage extends BasePage {
44
Navigator.pushNamed(context, Routes.restoreWalletFromKeys),
45
image: _imageKeys,
46
aspectRatioImage: _aspectRatioImage,
44
- titleColor: Palette.cakeGreen,
45
- color: Palette.cakeGreen,
47
+ titleColor: Palette.cakeGreen,
48
+ color: Palette.cakeGreen,
49
title: S.of(context).restore_title_from_keys,
50
description: S.of(context).restore_description_from_keys,
51
textButton: S.of(context).restore_next,
lib/src/screens/restore/widgets/restore_button.dart
+18
-16
@@ -2,15 +2,6 @@ import 'package:flutter/material.dart';
2
import 'package:cake_wallet/palette.dart';
3
4
class RestoreButton extends StatelessWidget {
5
- final VoidCallback onPressed;
6
- final Image image;
7
- final double aspectRatioImage;
8
- final Color color;
9
- final Color titleColor;
10
- final String title;
11
- final String description;
12
- final String textButton;
13
-
5
const RestoreButton(
6
{@required this.onPressed,
7
@required this.image,
@@ -21,9 +12,17 @@ class RestoreButton extends StatelessWidget {
12
this.description = '',
13
this.textButton = ''});
14
15
+ final VoidCallback onPressed;
16
+ final Image image;
17
+ final double aspectRatioImage;
18
+ final Color color;
19
+ final Color titleColor;
20
+ final String title;
21
+ final String description;
22
+ final String textButton;
23
+
24
@override
25
Widget build(BuildContext context) {
26
-
26
return Container(
27
margin: EdgeInsets.only(top: 20.0, bottom: 20.0),
28
decoration: BoxDecoration(
@@ -71,11 +70,11 @@ class RestoreButton extends StatelessWidget {
70
child: Text(
71
description,
72
textAlign: TextAlign.center,
74
- style:
75
- TextStyle(
76
- color: Theme.of(context).accentTextTheme.subhead.color,
77
- fontSize: 14.0,
78
- height: 1.4),
73
+ style: TextStyle(
74
+ color:
75
+ Theme.of(context).accentTextTheme.subhead.color,
76
+ fontSize: 14.0,
77
+ height: 1.4),
78
),
79
)
80
],
@@ -88,7 +87,10 @@ class RestoreButton extends StatelessWidget {
87
decoration: BoxDecoration(
88
border: Border(
89
top: BorderSide(
91
- color: Theme.of(context).accentTextTheme.headline.decorationColor,
90
+ color: Theme.of(context)
91
+ .accentTextTheme
92
+ .headline
93
+ .decorationColor,
94
width: 1.15)),
95
color: Colors.transparent,
96
),
lib/src/screens/root/root.dart
+3
-3
@@ -1,11 +1,9 @@
1
-import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart';
1
import 'package:flutter/material.dart';
2
import 'package:flutter_mobx/flutter_mobx.dart';
3
import 'package:hive/hive.dart';
4
import 'package:provider/provider.dart';
5
import 'package:shared_preferences/shared_preferences.dart';
6
import 'package:cake_wallet/routes.dart';
8
-import 'package:cake_wallet/router.dart';
7
import 'package:cake_wallet/src/stores/authentication/authentication_store.dart';
8
import 'package:cake_wallet/src/stores/price/price_store.dart';
9
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
@@ -19,6 +17,8 @@ import 'package:cake_wallet/src/domain/monero/transaction_description.dart';
17
import 'package:cake_wallet/src/screens/auth/create_login_page.dart';
18
import 'package:cake_wallet/src/screens/seed/create_seed_page.dart';
19
import 'package:cake_wallet/src/screens/dashboard/create_dashboard_page.dart';
20
+import 'package:cake_wallet/src/screens/auth/auth_page.dart';
21
+import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart';
22
23
class Root extends StatefulWidget {
24
Root({Key key}) : super(key: key);
@@ -81,7 +81,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
81
82
WidgetsBinding.instance.addPostFrameCallback((_) {
83
Navigator.of(context).pushNamed(Routes.unlock,
84
- arguments: (isAuthenticatedSuccessfully, auth) {
84
+ arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) {
85
if (!isAuthenticatedSuccessfully) {
86
return;
87
}
lib/src/screens/seed/seed_page.dart
+7
-2
@@ -11,14 +11,19 @@ import 'package:cake_wallet/src/stores/wallet_seed/wallet_seed_store.dart';
11
import 'package:cake_wallet/src/screens/base_page.dart';
12
13
class SeedPage extends BasePage {
14
+ SeedPage({this.onCloseCallback});
15
+
16
static final image = Image.asset('assets/images/seed_image.png');
17
+
18
+ @override
19
bool get isModalBackButton => true;
20
+
21
+ @override
22
String get title => S.current.seed_title;
23
24
final VoidCallback onCloseCallback;
25
20
- SeedPage({this.onCloseCallback});
21
-
26
+ @override
27
void onClose(BuildContext context) =>
28
onCloseCallback != null ? onCloseCallback() : Navigator.of(context).pop();
29
lib/src/screens/send/send_page.dart
+19
-14
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/src/screens/auth/auth_page.dart';
2
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
3
import 'package:flutter/cupertino.dart';
4
import 'package:flutter/material.dart';
@@ -23,8 +24,13 @@ import 'package:cake_wallet/src/domain/common/sync_status.dart';
24
import 'package:cake_wallet/src/stores/sync/sync_store.dart';
25
26
class SendPage extends BasePage {
27
+ @override
28
String get title => S.current.send_title;
29
+
30
+ @override
31
bool get isModalBackButton => true;
32
+
33
+ @override
34
bool get resizeToAvoidBottomPadding => false;
35
36
@override
@@ -212,7 +218,7 @@ class SendFormState extends State<SendForm> {
218
signed: false, decimal: false),
219
inputFormatters: [
220
BlacklistingTextInputFormatter(
215
- new RegExp('[\\-|\\ |\\,]'))
221
+ RegExp('[\\-|\\ |\\,]'))
222
],
223
decoration: InputDecoration(
224
prefixIcon: Padding(
@@ -272,7 +278,7 @@ class SendFormState extends State<SendForm> {
278
signed: false, decimal: false),
279
inputFormatters: [
280
BlacklistingTextInputFormatter(
275
- new RegExp('[\\-|\\ |\\,]'))
281
+ RegExp('[\\-|\\ |\\,]'))
282
],
283
decoration: InputDecoration(
284
prefixIcon: Padding(
@@ -353,7 +359,7 @@ class SendFormState extends State<SendForm> {
359
FocusScope.of(context).requestFocus(FocusNode());
360
361
if (_formKey.currentState.validate()) {
356
- await showDialog(
362
+ await showDialog<void>(
363
context: context,
364
builder: (dialogContext) {
365
return AlertDialog(
@@ -364,12 +370,11 @@ class SendFormState extends State<SendForm> {
370
FlatButton(
371
child: Text(S.of(context).send),
372
onPressed: () async {
367
- Navigator.of(dialogContext)
368
- .popAndPushNamed(
369
- Routes.auth,
370
- arguments:
371
- (isAuthenticatedSuccessfully,
372
- auth) {
373
+ await Navigator.of(dialogContext)
374
+ .popAndPushNamed(Routes.auth,
375
+ arguments: (bool
376
+ isAuthenticatedSuccessfully,
377
+ AuthPageState auth) {
378
if (!isAuthenticatedSuccessfully) {
379
return;
380
}
@@ -408,13 +413,13 @@ class SendFormState extends State<SendForm> {
413
414
final sendStore = Provider.of<SendStore>(context);
415
411
- reaction((_) => sendStore.fiatAmount, (amount) {
416
+ reaction((_) => sendStore.fiatAmount, (String amount) {
417
if (amount != _fiatAmountController.text) {
418
_fiatAmountController.text = amount;
419
}
420
});
421
417
- reaction((_) => sendStore.cryptoAmount, (amount) {
422
+ reaction((_) => sendStore.cryptoAmount, (String amount) {
423
if (amount != _cryptoAmountController.text) {
424
_cryptoAmountController.text = amount;
425
}
@@ -436,10 +441,10 @@ class SendFormState extends State<SendForm> {
441
}
442
});
443
439
- reaction((_) => sendStore.state, (state) {
444
+ reaction((_) => sendStore.state, (SendingState state) {
445
if (state is SendingFailed) {
446
WidgetsBinding.instance.addPostFrameCallback((_) {
442
- showDialog(
447
+ showDialog<void>(
448
context: context,
449
builder: (BuildContext context) {
450
return AlertDialog(
@@ -457,7 +462,7 @@ class SendFormState extends State<SendForm> {
462
463
if (state is TransactionCreatedSuccessfully) {
464
WidgetsBinding.instance.addPostFrameCallback((_) {
460
- showDialog(
465
+ showDialog<void>(
466
context: context,
467
builder: (BuildContext context) {
468
return AlertDialog(
lib/src/screens/settings/change_language.dart
+3
-2
@@ -21,7 +21,8 @@ const Map<String, String> _languages = {
21
};
22
23
class ChangeLanguage extends BasePage {
24
- get title => S.current.settings_change_language;
24
+ @override
25
+ String get title => S.current.settings_change_language;
26
27
@override
28
Widget body(BuildContext context) {
@@ -50,7 +51,7 @@ class ChangeLanguage extends BasePage {
51
),
52
onTap: () async {
53
if (!isCurrent) {
53
- await showDialog(
54
+ await showDialog<void>(
55
context: context,
56
builder: (BuildContext context) {
57
return AlertDialog(
lib/src/screens/settings/enter_pin_code.dart
+130
-139
@@ -7,39 +7,41 @@ import 'package:cake_wallet/theme_changer.dart';
7
import 'package:cake_wallet/themes.dart';
8
import 'package:cake_wallet/generated/i18n.dart';
9
10
-class EnterPinCode extends StatefulWidget{
10
+class EnterPinCode extends StatefulWidget {
11
+ const EnterPinCode(this.currentPinLength, this.currentPin);
12
13
final int currentPinLength;
14
final List<int> currentPin;
15
15
- const EnterPinCode(this.currentPinLength, this.currentPin);
16
-
16
@override
18
- createState() => EnterPinCodeState(currentPinLength, currentPin);
19
-
17
+ EnterPinCodeState createState() =>
18
+ EnterPinCodeState(currentPinLength, currentPin);
19
}
20
22
-class EnterPinCodeState extends State<EnterPinCode>{
23
- GlobalKey _gridViewKey = GlobalKey();
21
+class EnterPinCodeState extends State<EnterPinCode> {
22
+ EnterPinCodeState(this.pinLength, this.currentPin);
23
24
+ final _gridViewKey = GlobalKey();
25
final _closeButtonImage = Image.asset('assets/images/close_button.png');
26
- final _closeButtonImageDarkTheme = Image.asset('assets/images/close_button_dark_theme.png');
26
+ final _closeButtonImageDarkTheme =
27
+ Image.asset('assets/images/close_button_dark_theme.png');
28
static final deleteIconImage = Image.asset('assets/images/delete_icon.png');
29
final int pinLength;
30
final List<int> currentPin;
31
List<int> pin;
32
double _aspectRatio = 0;
33
33
- EnterPinCodeState(this.pinLength, this.currentPin);
34
+ void _calcualteCurrentAspectRatio() {
35
+ final renderBox =
36
+ _gridViewKey.currentContext.findRenderObject() as RenderBox;
37
+ final cellWidth = renderBox.size.width / 3;
38
+ final cellHeight = renderBox.size.height / 4;
39
35
- _getCurrentAspectRatio(){
36
- final RenderBox renderBox = _gridViewKey.currentContext.findRenderObject();
40
+ if (cellWidth > 0 && cellHeight > 0) {
41
+ _aspectRatio = cellWidth / cellHeight;
42
+ }
43
38
- double cellWidth = renderBox.size.width/3;
39
- double cellHeight = renderBox.size.height/4;
40
- if (cellWidth > 0 && cellHeight > 0) _aspectRatio = cellWidth/cellHeight;
41
- setState(() {
42
- });
44
+ setState(() {});
45
}
46
47
@override
@@ -49,130 +51,125 @@ class EnterPinCodeState extends State<EnterPinCode>{
51
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
52
}
53
52
- _afterLayout(_) {
53
- _getCurrentAspectRatio();
54
- }
54
+ void _afterLayout(dynamic _) => _calcualteCurrentAspectRatio();
55
56
@override
57
Widget build(BuildContext context) {
58
-
59
- ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
60
- bool _isDarkTheme;
61
-
62
- if (_themeChanger.getTheme() == Themes.darkTheme) _isDarkTheme = true;
63
- else _isDarkTheme = false;
58
+ final _themeChanger = Provider.of<ThemeChanger>(context);
59
+ final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
60
61
return Scaffold(
62
backgroundColor: Theme.of(context).backgroundColor,
63
appBar: CupertinoNavigationBar(
68
- leading: ButtonTheme(
69
- minWidth: double.minPositive,
70
- child: FlatButton(
71
- onPressed: (){ Navigator.pop(context, false); },
72
- child: _isDarkTheme ? _closeButtonImageDarkTheme : _closeButtonImage
64
+ leading: ButtonTheme(
65
+ minWidth: double.minPositive,
66
+ child: FlatButton(
67
+ onPressed: () {
68
+ Navigator.pop(context, false);
69
+ },
70
+ child: _isDarkTheme
71
+ ? _closeButtonImageDarkTheme
72
+ : _closeButtonImage),
73
),
74
- ),
75
- backgroundColor: Theme.of(context).backgroundColor,
76
- border: null,
77
- ),
74
+ backgroundColor: Theme.of(context).backgroundColor,
75
+ border: null),
76
body: SafeArea(
79
- child: Container(
80
- padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0),
81
- child: Column(
82
- children: <Widget>[
83
- Spacer(flex: 2),
84
- Text(S.of(context).enter_your_pin,
85
- style: TextStyle(
86
- fontSize: 24,
87
- color: Palette.wildDarkBlue
88
- )
89
- ),
90
- Spacer(flex: 3),
91
- Container(
92
- width: 180,
93
- child: Row(
94
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
95
- children: List.generate(pinLength, (index) {
96
- const size = 10.0;
97
- final isFilled = pin[index] != null;
98
-
99
- return Container(
100
- width: size,
101
- height: size,
102
- decoration: BoxDecoration(
103
- shape: BoxShape.circle,
104
- color: isFilled ? Palette.deepPurple : Colors.transparent,
105
- border: Border.all(color: Palette.wildDarkBlue),
106
- ));
107
- }),
108
- ),
77
+ child: Container(
78
+ padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0),
79
+ child: Column(
80
+ children: <Widget>[
81
+ Spacer(flex: 2),
82
+ Text(S.of(context).enter_your_pin,
83
+ style: TextStyle(fontSize: 24, color: Palette.wildDarkBlue)),
84
+ Spacer(flex: 3),
85
+ Container(
86
+ width: 180,
87
+ child: Row(
88
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
89
+ children: List.generate(pinLength, (index) {
90
+ const size = 10.0;
91
+ final isFilled = pin[index] != null;
92
+
93
+ return Container(
94
+ width: size,
95
+ height: size,
96
+ decoration: BoxDecoration(
97
+ shape: BoxShape.circle,
98
+ color:
99
+ isFilled ? Palette.deepPurple : Colors.transparent,
100
+ border: Border.all(color: Palette.wildDarkBlue),
101
+ ));
102
+ }),
103
),
110
- Spacer(flex: 3),
111
- Flexible(
112
- flex: 24,
113
- child: Container(
114
- key: _gridViewKey,
115
- child: _aspectRatio > 0 ? GridView.count(
116
- crossAxisCount: 3,
117
- childAspectRatio: _aspectRatio,
118
- physics: const NeverScrollableScrollPhysics(),
119
- children: List.generate(12, (index) {
120
-
121
- if (index == 9) {
122
- return Container(
123
- margin: EdgeInsets.all(5.0),
124
- decoration: BoxDecoration(
125
- shape: BoxShape.circle,
126
- color: _isDarkTheme ? PaletteDark.darkThemePinButton
127
- : Palette.darkGrey,
128
- ),
129
- );
130
- } else if (index == 10) {
131
- index = 0;
132
- } else if (index == 11) {
133
- return Container(
134
- margin: EdgeInsets.all(5.0),
135
- child: FlatButton(
136
- onPressed: () { _pop(); },
137
- color: _isDarkTheme ? PaletteDark.darkThemePinButton
138
- : Palette.darkGrey,
139
- shape: CircleBorder(),
140
- child: deleteIconImage,
141
- ),
142
- );
143
- } else {
144
- index++;
145
- }
146
-
147
- return Container(
148
- margin: EdgeInsets.all(5.0),
149
- child: FlatButton(
150
- onPressed: () { _push(index); },
151
- color: _isDarkTheme ? PaletteDark.darkThemePinDigitButton
152
- : Palette.creamyGrey,
153
- shape: CircleBorder(),
154
- child: Text(
155
- '$index',
156
- style: TextStyle(
157
- fontSize: 23.0,
158
- color: Palette.blueGrey
159
- )
160
- ),
161
- ),
162
- );
163
- }),
164
- ) : null
165
- )
166
- )
167
- ],
168
- ),
169
- )
170
- ),
104
+ ),
105
+ Spacer(flex: 3),
106
+ Flexible(
107
+ flex: 24,
108
+ child: Container(
109
+ key: _gridViewKey,
110
+ child: _aspectRatio > 0
111
+ ? GridView.count(
112
+ crossAxisCount: 3,
113
+ childAspectRatio: _aspectRatio,
114
+ physics: const NeverScrollableScrollPhysics(),
115
+ children: List.generate(12, (index) {
116
+ if (index == 9) {
117
+ return Container(
118
+ margin: EdgeInsets.all(5.0),
119
+ decoration: BoxDecoration(
120
+ shape: BoxShape.circle,
121
+ color: _isDarkTheme
122
+ ? PaletteDark.darkThemePinButton
123
+ : Palette.darkGrey,
124
+ ),
125
+ );
126
+ } else if (index == 10) {
127
+ index = 0;
128
+ } else if (index == 11) {
129
+ return Container(
130
+ margin: EdgeInsets.all(5.0),
131
+ child: FlatButton(
132
+ onPressed: () {
133
+ _pop();
134
+ },
135
+ color: _isDarkTheme
136
+ ? PaletteDark.darkThemePinButton
137
+ : Palette.darkGrey,
138
+ shape: CircleBorder(),
139
+ child: deleteIconImage,
140
+ ),
141
+ );
142
+ } else {
143
+ index++;
144
+ }
145
+
146
+ return Container(
147
+ margin: EdgeInsets.all(5.0),
148
+ child: FlatButton(
149
+ onPressed: () {
150
+ _push(index);
151
+ },
152
+ color: _isDarkTheme
153
+ ? PaletteDark.darkThemePinDigitButton
154
+ : Palette.creamyGrey,
155
+ shape: CircleBorder(),
156
+ child: Text('$index',
157
+ style: TextStyle(
158
+ fontSize: 23.0,
159
+ color: Palette.blueGrey)),
160
+ ),
161
+ );
162
+ }),
163
+ )
164
+ : null))
165
+ ],
166
+ ),
167
+ )),
168
);
169
}
170
174
- _showIncorrectPinDialog(BuildContext context) async {
175
- await showDialog(
171
+ void _showIncorrectPinDialog(BuildContext context) async {
172
+ await showDialog<void>(
173
context: context,
174
builder: (BuildContext context) {
175
return AlertDialog(
@@ -186,8 +183,7 @@ class EnterPinCodeState extends State<EnterPinCode>{
183
),
184
],
185
);
189
- }
190
- );
186
+ });
187
}
188
189
void _push(int num) {
@@ -202,20 +198,16 @@ class EnterPinCodeState extends State<EnterPinCode>{
198
}
199
}
200
205
- if (_pinLength() == pinLength) {
206
-
207
- if (listEquals<int>(pin, currentPin)){
201
+ final currentPinLength = _pinLength();
202
203
+ if (currentPinLength == pinLength) {
204
+ if (listEquals<int>(pin, currentPin)) {
205
Navigator.pop(context, true);
210
-
206
} else {
212
-
207
Navigator.pop(context, false);
208
209
_showIncorrectPinDialog(context);
216
-
210
}
218
-
211
}
212
}
213
@@ -226,7 +218,7 @@ class EnterPinCodeState extends State<EnterPinCode>{
218
219
for (var i = pin.length - 1; i >= 0; i--) {
220
if (pin[i] != null) {
229
- setState(() => pin[i] = null);
221
+ setState(() => pin[i] = null);
222
break;
223
}
224
}
@@ -241,5 +233,4 @@ class EnterPinCodeState extends State<EnterPinCode>{
233
return v;
234
});
235
}
244
-
245
-}
\ No newline at end of file
236
+}
lib/src/screens/settings/items/settings_item.dart
+10
-9
@@ -2,6 +2,15 @@ import 'package:flutter/material.dart';
2
import 'package:cake_wallet/src/screens/settings/attributes.dart';
3
4
class SettingsItem {
5
+ SettingsItem(
6
+ {this.onTaped,
7
+ this.title,
8
+ this.link,
9
+ this.image,
10
+ this.widget,
11
+ this.attribute,
12
+ this.widgetBuilder});
13
+
14
final VoidCallback onTaped;
15
final String title;
16
final String link;
@@ -9,12 +18,4 @@ class SettingsItem {
18
final Widget widget;
19
final Attributes attribute;
20
final WidgetBuilder widgetBuilder;
12
-
13
- SettingsItem({this.onTaped,
14
- this.title,
15
- this.link,
16
- this.image,
17
- this.widget,
18
- this.attribute,
19
- this.widgetBuilder});
20
-}
\ No newline at end of file
21
+}
lib/src/screens/settings/settings.dart
+28
-18
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/src/screens/auth/auth_page.dart';
2
import 'package:flutter/material.dart';
3
import 'package:flutter/cupertino.dart';
4
import 'package:cake_wallet/palette.dart';
@@ -25,8 +26,13 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_text_list_row.
26
import 'package:cake_wallet/src/screens/settings/widgets/settings_raw_widget_list_row.dart';
27
28
class SettingsPage extends BasePage {
29
+ @override
30
String get title => S.current.settings_title;
31
+
32
+ @override
33
bool get isModalBackButton => true;
34
+
35
+ @override
36
Color get backgroundColor => Palette.lightGrey2;
37
38
@override
@@ -37,7 +43,7 @@ class SettingsPage extends BasePage {
43
44
class SettingsForm extends StatefulWidget {
45
@override
40
- createState() => SettingsFormState();
46
+ SettingsFormState createState() => SettingsFormState();
47
}
48
49
class SettingsFormState extends State<SettingsForm> {
@@ -52,13 +58,13 @@ class SettingsFormState extends State<SettingsForm> {
58
final _changeNowUrl = 'mailto:support@changenow.io';
59
final _xmrToUrl = 'mailto:support@xmr.to';
60
55
- List<SettingsItem> _items = List<SettingsItem>();
61
+ final _items = List<SettingsItem>();
62
57
- _launchUrl(String url) async {
63
+ void _launchUrl(String url) async {
64
if (await canLaunch(url)) await launch(url);
65
}
66
61
- _setSettingsList() {
67
+ void _setSettingsList() {
68
final settingsStore = Provider.of<SettingsStore>(context);
69
70
settingsStore.setItemHeaders();
@@ -121,11 +127,13 @@ class SettingsFormState extends State<SettingsForm> {
127
SettingsItem(
128
onTaped: () {
129
Navigator.of(context).pushNamed(Routes.auth,
124
- arguments: (isAuthenticatedSuccessfully, auth) =>
130
+ arguments: (bool isAuthenticatedSuccessfully,
131
+ AuthPageState auth) =>
132
isAuthenticatedSuccessfully
133
? Navigator.of(context).popAndPushNamed(Routes.setupPin,
127
- arguments: (setupPinContext, _) =>
128
- Navigator.of(context).pop())
134
+ arguments:
135
+ (BuildContext setupPinContext, String _) =>
136
+ Navigator.of(context).pop())
137
: null);
138
},
139
title: ItemHeaders.changePIN,
@@ -263,7 +271,7 @@ class SettingsFormState extends State<SettingsForm> {
271
onTaped: () {
272
Navigator.push(
273
context,
266
- CupertinoPageRoute(
274
+ CupertinoPageRoute<void>(
275
builder: (BuildContext context) => DisclaimerPage()));
276
},
277
title: ItemHeaders.termsAndConditions,
@@ -276,7 +284,7 @@ class SettingsFormState extends State<SettingsForm> {
284
setState(() {});
285
}
286
279
- _afterLayout(_) => _setSettingsList();
287
+ void _afterLayout(dynamic _) => _setSettingsList();
288
289
@override
290
void initState() {
@@ -335,11 +343,12 @@ class SettingsFormState extends State<SettingsForm> {
343
final item = _items[index];
344
bool _isDrawDivider = true;
345
338
- if (item.attribute == Attributes.header)
346
+ if (item.attribute == Attributes.header) {
347
_isDrawDivider = false;
340
- else if (index < _items.length - 1) {
341
- if (_items[index + 1].attribute == Attributes.header)
348
+ } else if (index < _items.length - 1) {
349
+ if (_items[index + 1].attribute == Attributes.header) {
350
_isDrawDivider = false;
351
+ }
352
}
353
354
return Column(
@@ -413,33 +422,34 @@ class SettingsFormState extends State<SettingsForm> {
422
});
423
}
424
416
- void _setBalance(BuildContext context) async {
425
+ Future<void> _setBalance(BuildContext context) async {
426
final settingsStore = Provider.of<SettingsStore>(context);
427
final selectedDisplayMode =
428
await _presentPicker(context, BalanceDisplayMode.all);
429
430
if (selectedDisplayMode != null) {
422
- settingsStore.setCurrentBalanceDisplayMode(
431
+ await settingsStore.setCurrentBalanceDisplayMode(
432
balanceDisplayMode: selectedDisplayMode);
433
}
434
}
435
427
- void _setCurrency(BuildContext context) async {
436
+ Future<void> _setCurrency(BuildContext context) async {
437
final settingsStore = Provider.of<SettingsStore>(context);
438
final selectedCurrency = await _presentPicker(context, FiatCurrency.all);
439
440
if (selectedCurrency != null) {
432
- settingsStore.setCurrentFiatCurrency(currency: selectedCurrency);
441
+ await settingsStore.setCurrentFiatCurrency(currency: selectedCurrency);
442
}
443
}
444
436
- void _setTransactionPriority(BuildContext context) async {
445
+ Future<void> _setTransactionPriority(BuildContext context) async {
446
final settingsStore = Provider.of<SettingsStore>(context);
447
final selectedPriority =
448
await _presentPicker(context, TransactionPriority.all);
449
450
if (selectedPriority != null) {
442
- settingsStore.setCurrentTransactionPriority(priority: selectedPriority);
451
+ await settingsStore.setCurrentTransactionPriority(
452
+ priority: selectedPriority);
453
}
454
}
455
}
lib/src/screens/settings/widgets/settings_arrow_list_row.dart
+2
-2
@@ -4,12 +4,12 @@ import 'package:flutter_mobx/flutter_mobx.dart';
4
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
5
6
class SettingsArrowListRow extends StatelessWidget {
7
+ SettingsArrowListRow({@required this.onTaped, this.title});
8
+
9
final VoidCallback onTaped;
10
final String title;
11
final _cakeArrowImage = Image.asset('assets/images/cake_arrow.png');
12
11
- SettingsArrowListRow({@required this.onTaped, this.title});
12
-
13
@override
14
Widget build(BuildContext context) {
15
final settingsStore = Provider.of<SettingsStore>(context);
lib/src/screens/settings/widgets/settings_header_list_row.dart
+7
-8
@@ -5,10 +5,10 @@ import 'package:cake_wallet/palette.dart';
5
import 'package:provider/provider.dart';
6
7
class SettingsHeaderListRow extends StatelessWidget {
8
- final String title;
9
-
8
SettingsHeaderListRow({this.title});
9
10
+ final String title;
11
+
12
@override
13
Widget build(BuildContext context) {
14
final settingsStore = Provider.of<SettingsStore>(context);
@@ -25,10 +25,10 @@ class SettingsHeaderListRow extends StatelessWidget {
25
children: <Widget>[
26
Observer(
27
builder: (_) => Text(
28
- settingsStore.itemHeaders[title],
29
- style: TextStyle(
30
- fontSize: 15.0, color: Palette.wildDarkBlue),
31
- ))
28
+ settingsStore.itemHeaders[title],
29
+ style: TextStyle(
30
+ fontSize: 15.0, color: Palette.wildDarkBlue),
31
+ ))
32
],
33
),
34
),
@@ -38,5 +38,4 @@ class SettingsHeaderListRow extends StatelessWidget {
38
],
39
);
40
}
41
-
42
-}
\ No newline at end of file
41
+}
lib/src/screens/settings/widgets/settings_link_list_row.dart
+6
-9
@@ -2,16 +2,16 @@ import 'package:flutter/material.dart';
2
import 'package:cake_wallet/palette.dart';
3
4
class SettingsLinktListRow extends StatelessWidget {
5
+ SettingsLinktListRow(
6
+ {@required this.onTaped, this.title, this.link, this.image});
7
+
8
final VoidCallback onTaped;
9
final String title;
10
final String link;
11
final Image image;
12
10
- SettingsLinktListRow({@required this.onTaped, this.title, this.link, this.image});
11
-
13
@override
14
Widget build(BuildContext context) {
14
-
15
return Container(
16
color: Theme.of(context).accentTextTheme.headline.backgroundColor,
17
child: ListTile(
@@ -28,20 +28,17 @@ class SettingsLinktListRow extends StatelessWidget {
28
style: TextStyle(
29
fontSize: 15.0,
30
fontWeight: FontWeight.w500,
31
- color: Theme.of(context).primaryTextTheme.title.color
32
- ),
31
+ color: Theme.of(context).primaryTextTheme.title.color),
32
),
33
)
34
],
35
),
36
trailing: Text(
37
link,
39
- style:
40
- TextStyle(fontSize: 14.0, color: Palette.cakeGreen),
38
+ style: TextStyle(fontSize: 14.0, color: Palette.cakeGreen),
39
),
40
onTap: onTaped,
41
),
42
);
43
}
46
-
47
-}
\ No newline at end of file
44
+}
lib/src/screens/settings/widgets/settings_raw_widget_list_row.dart
+2
-3
@@ -1,13 +1,12 @@
1
import 'package:flutter/material.dart';
2
3
class SettingRawWidgetListRow extends StatelessWidget {
4
- final WidgetBuilder widgetBuilder;
5
-
4
SettingRawWidgetListRow({@required this.widgetBuilder});
5
6
+ final WidgetBuilder widgetBuilder;
7
+
8
@override
9
Widget build(BuildContext context) {
10
-
10
return Container(
11
color: Theme.of(context).accentTextTheme.headline.backgroundColor,
12
child: widgetBuilder(context) ?? Container(),
lib/src/screens/settings/widgets/settings_switch_list_row.dart
+6
-6
@@ -8,13 +8,13 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart';
8
import 'package:cake_wallet/src/widgets/standart_switch.dart';
9
10
class SettingsSwitchListRow extends StatelessWidget {
11
- final String title;
12
-
11
SettingsSwitchListRow({@required this.title});
12
13
+ final String title;
14
+
15
Widget _getSwitch(BuildContext context) {
16
final settingsStore = Provider.of<SettingsStore>(context);
17
- ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
17
+ final _themeChanger = Provider.of<ThemeChanger>(context);
18
19
if (settingsStore.itemHeaders[title] ==
20
S.of(context).settings_save_recipient_address) {
@@ -22,7 +22,7 @@ class SettingsSwitchListRow extends StatelessWidget {
22
builder: (_) => StandartSwitch(
23
value: settingsStore.shouldSaveRecipientAddress,
24
onTaped: () {
25
- bool _currentValue = !settingsStore.shouldSaveRecipientAddress;
25
+ final _currentValue = !settingsStore.shouldSaveRecipientAddress;
26
settingsStore.setSaveRecipientAddress(
27
shouldSaveRecipientAddress: _currentValue);
28
}));
@@ -34,7 +34,7 @@ class SettingsSwitchListRow extends StatelessWidget {
34
builder: (_) => StandartSwitch(
35
value: settingsStore.allowBiometricalAuthentication,
36
onTaped: () {
37
- bool _currentValue =
37
+ final _currentValue =
38
!settingsStore.allowBiometricalAuthentication;
39
settingsStore.setAllowBiometricalAuthentication(
40
allowBiometricalAuthentication: _currentValue);
@@ -46,7 +46,7 @@ class SettingsSwitchListRow extends StatelessWidget {
46
builder: (_) => StandartSwitch(
47
value: settingsStore.isDarkTheme,
48
onTaped: () {
49
- bool _currentValue = !settingsStore.isDarkTheme;
49
+ final _currentValue = !settingsStore.isDarkTheme;
50
settingsStore.saveDarkTheme(isDarkTheme: _currentValue);
51
_themeChanger.setTheme(
52
_currentValue ? Themes.darkTheme : Themes.lightTheme);
lib/src/screens/settings/widgets/settings_text_list_row.dart
+2
-2
@@ -4,12 +4,12 @@ import 'package:flutter_mobx/flutter_mobx.dart';
4
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
5
6
class SettingsTextListRow extends StatelessWidget {
7
+ SettingsTextListRow({@required this.onTaped, this.title, this.widget});
8
+
9
final VoidCallback onTaped;
10
final String title;
11
final Widget widget;
12
11
- SettingsTextListRow({@required this.onTaped, this.title, this.widget});
12
-
13
@override
14
Widget build(BuildContext context) {
15
final settingsStore = Provider.of<SettingsStore>(context);
lib/src/screens/setup_pin_code/setup_pin_code.dart
+12
-13
@@ -9,24 +9,24 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart';
9
import 'package:cake_wallet/generated/i18n.dart';
10
11
class SetupPinCodePage extends BasePage {
12
+ SetupPinCodePage({this.onPinCodeSetup});
13
+
14
final Function(BuildContext, String) onPinCodeSetup;
15
16
@override
17
String get title => S.current.setup_pin;
18
17
- SetupPinCodePage({this.onPinCodeSetup});
18
-
19
@override
20
Widget body(BuildContext context) =>
21
SetupPinCodeForm(onPinCodeSetup: onPinCodeSetup, hasLengthSwitcher: true);
22
}
23
24
class SetupPinCodeForm extends PinCodeWidget {
25
- final Function(BuildContext, String) onPinCodeSetup;
26
- final bool hasLengthSwitcher;
27
-
25
SetupPinCodeForm(
29
- {@required this.onPinCodeSetup, @required this.hasLengthSwitcher});
26
+ {@required this.onPinCodeSetup, @required bool hasLengthSwitcher})
27
+ : super(hasLengthSwitcher: hasLengthSwitcher);
28
+
29
+ final Function(BuildContext, String) onPinCodeSetup;
30
31
@override
32
_SetupPinCodeFormState createState() => _SetupPinCodeFormState();
@@ -34,17 +34,16 @@ class SetupPinCodeForm extends PinCodeWidget {
34
35
class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
36
extends PinCodeState<WidgetType> {
37
+ _SetupPinCodeFormState() {
38
+ title = S.current.enter_your_pin;
39
+ }
40
38
- bool isEnteredOriginalPin() => !(_originalPin.length == 0);
41
+ bool isEnteredOriginalPin() => _originalPin.isNotEmpty;
42
Function(BuildContext) onPinCodeSetup;
43
List<int> _originalPin = [];
44
UserStore _userStore;
45
SettingsStore _settingsStore;
46
44
- _SetupPinCodeFormState() {
45
- title = S.current.enter_your_pin;
46
- }
47
-
47
@override
48
void onPinCodeEntered(PinCodeState state) {
49
if (!isEnteredOriginalPin()) {
@@ -57,7 +56,7 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
56
_userStore.set(password: pin);
57
_settingsStore.setDefaultPinLength(pinLength: state.pinLength);
58
60
- showDialog(
59
+ showDialog<void>(
60
context: context,
61
barrierDismissible: false,
62
builder: (BuildContext context) {
@@ -76,7 +75,7 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
75
);
76
});
77
} else {
79
- showDialog(
78
+ showDialog<void>(
79
context: context,
80
builder: (BuildContext context) {
81
return AlertDialog(
lib/src/screens/show_keys/show_keys_page.dart
+4
-1
@@ -9,7 +9,10 @@ import 'package:cake_wallet/src/stores/wallet/wallet_keys_store.dart';
9
import 'package:cake_wallet/src/screens/base_page.dart';
10
11
class ShowKeysPage extends BasePage {
12
+ @override
13
bool get isModalBackButton => true;
14
+
15
+ @override
16
String get title => S.current.wallet_keys;
17
18
@override
@@ -20,7 +23,7 @@ class ShowKeysPage extends BasePage {
23
padding: EdgeInsets.only(top: 20.0, bottom: 20.0, left: 20, right: 20),
24
child: Observer(
25
builder: (_) {
23
- Map<String, String> keysMap = {
26
+ final keysMap = {
27
S.of(context).view_key_public: walletKeysStore.publicViewKey,
28
S.of(context).view_key_private: walletKeysStore.privateViewKey,
29
S.of(context).spend_key_public: walletKeysStore.publicSpendKey,
lib/src/screens/subaddress/new_subaddress_page.dart
+4
-3
@@ -11,6 +11,7 @@ import 'package:cake_wallet/src/screens/base_page.dart';
11
import 'package:cake_wallet/palette.dart';
12
13
class NewSubaddressPage extends BasePage {
14
+ @override
15
String get title => S.current.new_subaddress_title;
16
17
@override
@@ -21,7 +22,7 @@ class NewSubaddressPage extends BasePage {
22
final subaddressCreationStore =
23
Provider.of<SubadrressCreationStore>(context);
24
24
- reaction((_) => subaddressCreationStore.state, (state) {
25
+ reaction((_) => subaddressCreationStore.state, (SubaddressCreationState state) {
26
if (state is SubaddressCreatedSuccessfully) {
27
WidgetsBinding.instance
28
.addPostFrameCallback((_) => Navigator.of(context).pop());
@@ -58,8 +59,8 @@ class NewSubaddressFormState extends State<NewSubaddressForm> {
59
hintStyle: TextStyle(color: Theme.of(context).hintColor),
60
hintText: S.of(context).new_subaddress_label_name,
61
focusedBorder: UnderlineInputBorder(
61
- borderSide: BorderSide(
62
- color: Palette.cakeGreen, width: 2.0)),
62
+ borderSide:
63
+ BorderSide(color: Palette.cakeGreen, width: 2.0)),
64
enabledBorder: UnderlineInputBorder(
65
borderSide: BorderSide(
66
color: Theme.of(context).focusColor,
lib/src/screens/subaddress/subaddress_list_page.dart
+7
-2
@@ -8,11 +8,16 @@ import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
8
import 'package:cake_wallet/src/screens/base_page.dart';
9
10
class SubaddressListPage extends BasePage {
11
+ SubaddressListPage();
12
+
13
+ @override
14
bool get isModalBackButton => true;
15
+
16
+ @override
17
String get title => S.current.subaddress_title;
13
- AppBarStyle get appBarStyle => AppBarStyle.withShadow;
18
15
- SubaddressListPage();
19
+ @override
20
+ AppBarStyle get appBarStyle => AppBarStyle.withShadow;
21
22
@override
23
Widget body(BuildContext context) {
lib/src/screens/trade_details/trade_details_page.dart
+5
-1
@@ -10,7 +10,10 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d
10
import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.dart';
11
12
class TradeDetailsPage extends BasePage {
13
+ @override
14
String get title => S.current.trade_details_title;
15
+
16
+ @override
17
bool get isModalBackButton => true;
18
19
@override
@@ -54,7 +57,8 @@ class TradeDetailsPage extends BasePage {
57
color: Theme.of(context).dividerTheme.color,
58
height: 1.0,
59
),
57
- padding: EdgeInsets.only(left: 25, top: 10, right: 25, bottom: 15),
60
+ padding:
61
+ EdgeInsets.only(left: 25, top: 10, right: 25, bottom: 15),
62
itemCount: items.length,
63
itemBuilder: (BuildContext context, int index) {
64
final item = items[index];
lib/src/screens/transaction_details/standart_list_item.dart
+3
-3
@@ -1,6 +1,6 @@
1
class StandartListItem {
2
+ StandartListItem({this.title, this.value});
3
+
4
final String title;
5
final String value;
4
-
5
- StandartListItem({this.title, this.value});
6
-}
\ No newline at end of file
6
+}
lib/src/screens/transaction_details/standart_list_row.dart
+3
-6
@@ -2,14 +2,13 @@ import 'package:flutter/material.dart';
2
import 'package:cake_wallet/palette.dart';
3
4
class StandartListRow extends StatelessWidget {
5
+ StandartListRow({this.title, this.value});
6
+
7
final String title;
8
final String value;
9
8
- StandartListRow({this.title, this.value});
9
-
10
@override
11
Widget build(BuildContext context) {
12
-
12
return Padding(
13
padding: const EdgeInsets.only(top: 10, bottom: 10),
14
child: Column(
@@ -23,9 +22,7 @@ class StandartListRow extends StatelessWidget {
22
Padding(
23
padding: const EdgeInsets.only(top: 5),
24
child: Text(value,
26
- style: TextStyle(
27
- fontSize: 14,
28
- color: Palette.wildDarkBlue)),
25
+ style: TextStyle(fontSize: 14, color: Palette.wildDarkBlue)),
26
)
27
]),
28
);
lib/src/screens/transaction_details/transaction_details_page.dart
+16
-12
@@ -11,12 +11,15 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.da
11
import 'package:cake_wallet/src/screens/base_page.dart';
12
13
class TransactionDetailsPage extends BasePage {
14
- bool get isModalBackButton => true;
15
- String get title => S.current.transaction_details_title;
14
+ TransactionDetailsPage({this.transactionInfo});
15
16
final TransactionInfo transactionInfo;
17
19
- TransactionDetailsPage({this.transactionInfo});
18
+ @override
19
+ bool get isModalBackButton => true;
20
+
21
+ @override
22
+ String get title => S.current.transaction_details_title;
23
24
@override
25
Widget body(BuildContext context) {
@@ -28,23 +31,23 @@ class TransactionDetailsPage extends BasePage {
31
}
32
33
class TransactionDetailsForm extends StatefulWidget {
31
- final TransactionInfo transactionInfo;
32
- final SettingsStore settingsStore;
33
-
34
TransactionDetailsForm(
35
{@required this.transactionInfo, @required this.settingsStore});
36
37
+ final TransactionInfo transactionInfo;
38
+ final SettingsStore settingsStore;
39
+
40
@override
38
- createState() => TransactionDetailsFormState();
41
+ TransactionDetailsFormState createState() => TransactionDetailsFormState();
42
}
43
44
class TransactionDetailsFormState extends State<TransactionDetailsForm> {
45
final DateFormat _dateFormat = DateFormat('dd.MM.yyyy, HH:mm');
43
- List<StandartListItem> _items = List<StandartListItem>();
46
+ final _items = List<StandartListItem>();
47
48
@override
49
void initState() {
47
- List<StandartListItem> items = [
50
+ final items = [
51
StandartListItem(
52
title: S.current.transaction_details_transaction_id,
53
value: widget.transactionInfo.id),
@@ -59,10 +62,11 @@ class TransactionDetailsFormState extends State<TransactionDetailsForm> {
62
value: widget.transactionInfo.amountFormatted())
63
];
64
62
- if (widget.settingsStore.shouldSaveRecipientAddress && widget.transactionInfo.recipientAddress != null) {
65
+ if (widget.settingsStore.shouldSaveRecipientAddress &&
66
+ widget.transactionInfo.recipientAddress != null) {
67
items.add(StandartListItem(
64
- title: S.current.transaction_details_recipient_address,
65
- value: widget.transactionInfo.recipientAddress));
68
+ title: S.current.transaction_details_recipient_address,
69
+ value: widget.transactionInfo.recipientAddress));
70
}
71
72
_items.addAll(items);
lib/src/screens/wallet_list/wallet_list_page.dart
+9
-3
@@ -14,8 +14,13 @@ import 'package:cake_wallet/src/screens/wallet_list/wallet_menu.dart';
14
import 'package:cake_wallet/src/widgets/picker.dart';
15
16
class WalletListPage extends BasePage {
17
+ @override
18
bool get isModalBackButton => true;
19
+
20
+ @override
21
String get title => S.current.wallet_list_title;
22
+
23
+ @override
24
AppBarStyle get appBarStyle => AppBarStyle.withShadow;
25
26
@override
@@ -23,6 +28,7 @@ class WalletListPage extends BasePage {
28
}
29
30
class WalletListBody extends StatefulWidget {
31
+ @override
32
WalletListBodyState createState() => WalletListBodyState();
33
}
34
@@ -32,15 +38,15 @@ class WalletListBodyState extends State<WalletListBody> {
38
void presetMenuForWallet(WalletDescription wallet, bool isCurrentWallet,
39
BuildContext bodyContext) {
40
final walletMenu = WalletMenu(bodyContext);
35
- List<String> items = walletMenu.generateItemsForWalletMenu(isCurrentWallet);
41
+ final items = walletMenu.generateItemsForWalletMenu(isCurrentWallet);
42
37
- showDialog(
43
+ showDialog<void>(
44
context: bodyContext,
45
builder: (_) => Picker(
46
items: items,
47
selectedAtIndex: -1,
48
title: S.of(context).wallet_menu,
43
- onItemSelected: (item) => walletMenu.action(
49
+ onItemSelected: (String item) => walletMenu.action(
50
walletMenu.listItems.indexOf(item), wallet, isCurrentWallet)),
51
);
52
}
lib/src/screens/wallet_list/wallet_menu.dart
+47
-43
@@ -1,13 +1,16 @@
1
-import 'package:cake_wallet/src/domain/common/wallet_description.dart';
1
import 'package:flutter/material.dart';
2
import 'package:cake_wallet/routes.dart';
3
import 'package:provider/provider.dart';
5
-import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart';
4
import 'package:cake_wallet/generated/i18n.dart';
5
+import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart';
6
+import 'package:cake_wallet/src/domain/common/wallet_description.dart';
7
+import 'package:cake_wallet/src/screens/auth/auth_page.dart';
8
9
class WalletMenu {
10
+ WalletMenu(this.context);
11
12
final BuildContext context;
13
+
14
final List<String> listItems = [
15
S.current.wallet_list_load_wallet,
16
S.current.show_seed,
@@ -15,10 +18,8 @@ class WalletMenu {
18
S.current.rescan
19
];
20
18
- WalletMenu(this.context);
19
-
20
- List<String>generateItemsForWalletMenu(bool isCurrentWallet) {
21
- List<String> items = new List<String>();
21
+ List<String> generateItemsForWalletMenu(bool isCurrentWallet) {
22
+ final items = List<String>();
23
24
if (!isCurrentWallet) items.add(listItems[0]);
25
if (isCurrentWallet) items.add(listItems[1]);
@@ -29,52 +30,56 @@ class WalletMenu {
30
}
31
32
void action(int index, WalletDescription wallet, bool isCurrentWallet) {
32
- WalletListStore _walletListStore = Provider.of<WalletListStore>(context);
33
+ final _walletListStore = Provider.of<WalletListStore>(context);
34
35
switch (index) {
36
case 0:
36
- Navigator.of(context).pushNamed(Routes.auth,
37
- arguments: (isAuthenticatedSuccessfully, auth) async {
38
- if (!isAuthenticatedSuccessfully) {
39
- return;
40
- }
37
+ Navigator.of(context).pushNamed(Routes.auth, arguments:
38
+ (bool isAuthenticatedSuccessfully, AuthPageState auth) async {
39
+ if (!isAuthenticatedSuccessfully) {
40
+ return;
41
+ }
42
42
- try {
43
- auth.changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
44
- await _walletListStore.loadWallet(wallet);
45
- auth.close();
46
- Navigator.of(context).pop();
47
- } catch (e) {
48
- auth.changeProcessText(
49
- S.of(context).wallet_list_failed_to_load(wallet.name, e.toString()));
50
- }
43
+ try {
44
+ auth.changeProcessText(
45
+ S.of(context).wallet_list_loading_wallet(wallet.name));
46
+ await _walletListStore.loadWallet(wallet);
47
+ auth.close();
48
+ Navigator.of(context).pop();
49
+ } catch (e) {
50
+ auth.changeProcessText(S
51
+ .of(context)
52
+ .wallet_list_failed_to_load(wallet.name, e.toString()));
53
+ }
54
});
55
break;
56
case 1:
54
- Navigator.of(context).pushNamed(Routes.auth,
55
- arguments: (isAuthenticatedSuccessfully, auth) async {
56
- if (!isAuthenticatedSuccessfully) {
57
- return;
58
- }
59
- auth.close();
60
- Navigator.of(context).pushNamed(Routes.seed);
57
+ Navigator.of(context).pushNamed(Routes.auth, arguments:
58
+ (bool isAuthenticatedSuccessfully, AuthPageState auth) async {
59
+ if (!isAuthenticatedSuccessfully) {
60
+ return;
61
+ }
62
+ auth.close();
63
+ await Navigator.of(context).pushNamed(Routes.seed);
64
});
65
break;
66
case 2:
64
- Navigator.of(context).pushNamed(Routes.auth,
65
- arguments: (isAuthenticatedSuccessfully, auth) async {
66
- if (!isAuthenticatedSuccessfully) {
67
- return;
68
- }
67
+ Navigator.of(context).pushNamed(Routes.auth, arguments:
68
+ (bool isAuthenticatedSuccessfully, AuthPageState auth) async {
69
+ if (!isAuthenticatedSuccessfully) {
70
+ return;
71
+ }
72
70
- try {
71
- auth.changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name));
72
- await _walletListStore.remove(wallet);
73
- auth.close();
74
- } catch (e) {
75
- auth.changeProcessText(
76
- S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString()));
77
- }
73
+ try {
74
+ auth.changeProcessText(
75
+ S.of(context).wallet_list_removing_wallet(wallet.name));
76
+ await _walletListStore.remove(wallet);
77
+ auth.close();
78
+ } catch (e) {
79
+ auth.changeProcessText(S
80
+ .of(context)
81
+ .wallet_list_failed_to_remove(wallet.name, e.toString()));
82
+ }
83
});
84
break;
85
case 3:
@@ -84,5 +89,4 @@ class WalletMenu {
89
break;
90
}
91
}
87
-
88
-}
\ No newline at end of file
92
+}
lib/src/screens/welcome/welcome_page.dart
+3
-11
@@ -1,11 +1,8 @@
1
import 'package:flutter/material.dart';
2
-import 'package:provider/provider.dart';
2
import 'package:cake_wallet/palette.dart';
3
import 'package:cake_wallet/routes.dart';
4
import 'package:cake_wallet/src/widgets/primary_button.dart';
5
import 'package:cake_wallet/src/screens/base_page.dart';
7
-import 'package:cake_wallet/theme_changer.dart';
8
-import 'package:cake_wallet/themes.dart';
6
import 'package:cake_wallet/generated/i18n.dart';
7
8
class WelcomePage extends BasePage {
@@ -16,15 +13,10 @@ class WelcomePage extends BasePage {
13
14
@override
15
Widget build(BuildContext context) {
19
- ThemeChanger _themeChanger = Provider.of<ThemeChanger>(context);
20
- bool _isDarkTheme = (_themeChanger.getTheme() == Themes.darkTheme);
21
-
16
return Scaffold(
23
- backgroundColor:
24
- _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor,
25
- resizeToAvoidBottomPadding: false,
26
- body: SafeArea(child: body(context)),
27
- );
17
+ backgroundColor: Theme.of(context).backgroundColor,
18
+ resizeToAvoidBottomPadding: false,
19
+ body: SafeArea(child: body(context)));
20
}
21
22
@override
lib/src/start_updating_price.dart
+9
-6
@@ -1,4 +1,5 @@
1
import 'dart:async';
2
+import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
3
import 'package:flutter/foundation.dart';
4
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
5
import 'package:cake_wallet/src/domain/common/fetch_price.dart';
@@ -7,12 +8,14 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart';
8
9
bool _startedUpdatingPrice = false;
10
10
-_updatePrice(Map args) async =>
11
- await fetchPriceFor(fiat: args['fiat'], crypto: args['crypto']);
11
+Future<double> _updatePrice(Map args) async => await fetchPriceFor(
12
+ fiat: args['fiat'] as FiatCurrency,
13
+ crypto: args['crypto'] as CryptoCurrency);
14
13
-updatePrice(Map args) async => compute(_updatePrice, args);
15
+Future<double> updatePrice(Map args) async => compute(_updatePrice, args);
16
15
-startUpdatingPrice({SettingsStore settingsStore, PriceStore priceStore}) async {
17
+Future<void> startUpdatingPrice(
18
+ {SettingsStore settingsStore, PriceStore priceStore}) async {
19
if (_startedUpdatingPrice) {
20
return;
21
}
@@ -21,13 +24,13 @@ startUpdatingPrice({SettingsStore settingsStore, PriceStore priceStore}) async {
24
_startedUpdatingPrice = true;
25
26
final price = await updatePrice(
24
- {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto});
27
+ <String, dynamic>{'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto});
28
priceStore.changePriceForPair(
29
fiat: settingsStore.fiatCurrency, crypto: currentCrypto, price: price);
30
31
Timer.periodic(Duration(seconds: 30), (_) async {
32
final price = await updatePrice(
30
- {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto});
33
+ <String, dynamic>{'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto});
34
priceStore.changePriceForPair(
35
fiat: settingsStore.fiatCurrency, crypto: currentCrypto, price: price);
36
});
lib/src/stores/account_list/account_list_store.dart
+20
-20
@@ -13,6 +13,18 @@ part 'account_list_store.g.dart';
13
class AccountListStore = AcountListStoreBase with _$AccountListStore;
14
15
abstract class AcountListStoreBase with Store {
16
+ AcountListStoreBase({@required WalletService walletService}) {
17
+ accounts = [];
18
+ isAccountCreating = false;
19
+
20
+ if (walletService.currentWallet != null) {
21
+ _onWalletChanged(walletService.currentWallet);
22
+ }
23
+
24
+ _onWalletChangeSubscription =
25
+ walletService.onWalletChange.listen(_onWalletChanged);
26
+ }
27
+
28
@observable
29
List<Account> accounts;
30
@@ -29,18 +41,6 @@ abstract class AcountListStoreBase with Store {
41
StreamSubscription<Wallet> _onWalletChangeSubscription;
42
StreamSubscription<List<Account>> _onAccountsChangeSubscription;
43
32
- AcountListStoreBase({@required WalletService walletService}) {
33
- accounts = [];
34
- isAccountCreating = false;
35
-
36
- if (walletService.currentWallet != null) {
37
- _onWalletChanged(walletService.currentWallet);
38
- }
39
-
40
- _onWalletChangeSubscription =
41
- walletService.onWalletChange.listen(_onWalletChanged);
42
- }
43
-
44
@override
45
void dispose() {
46
_onWalletChangeSubscription.cancel();
@@ -52,8 +52,8 @@ abstract class AcountListStoreBase with Store {
52
super.dispose();
53
}
54
55
- Future updateAccountList() async {
56
- await _accountList.refresh();
55
+ void updateAccountList() {
56
+ _accountList.refresh();
57
accounts = _accountList.getAll();
58
}
59
@@ -61,7 +61,7 @@ abstract class AcountListStoreBase with Store {
61
try {
62
isAccountCreating = true;
63
await _accountList.addAccount(label: label);
64
- await updateAccountList();
64
+ updateAccountList();
65
isAccountCreating = false;
66
} catch (e) {
67
isAccountCreating = false;
@@ -70,19 +70,19 @@ abstract class AcountListStoreBase with Store {
70
71
Future renameAccount({int index, String label}) async {
72
await _accountList.setLabelSubaddress(accountIndex: index, label: label);
73
- await updateAccountList();
73
+ updateAccountList();
74
}
75
76
Future _onWalletChanged(Wallet wallet) async {
77
if (_onAccountsChangeSubscription != null) {
78
- _onAccountsChangeSubscription.cancel();
78
+ await _onAccountsChangeSubscription.cancel();
79
}
80
81
if (wallet is MoneroWallet) {
82
_accountList = wallet.getAccountList();
83
_onAccountsChangeSubscription =
84
_accountList.accounts.listen((accounts) => this.accounts = accounts);
85
- await updateAccountList();
85
+ updateAccountList();
86
87
return;
88
}
@@ -91,8 +91,8 @@ abstract class AcountListStoreBase with Store {
91
}
92
93
void validateAccountName(String value) {
94
- String p = '^[a-zA-Z0-9_]{1,15}\$';
95
- RegExp regExp = new RegExp(p);
94
+ const pattern = '^[a-zA-Z0-9_]{1,15}\$';
95
+ final regExp = RegExp(pattern);
96
isValid = regExp.hasMatch(value);
97
errorMessage = isValid ? null : S.current.error_text_account_name;
98
}
lib/src/stores/action_list/action_list_display_mode.dart
+1
-1
@@ -18,7 +18,7 @@ int serializeActionlistDisplayModes(List<ActionListDisplayMode> modes) {
18
}
19
20
List<ActionListDisplayMode> deserializeActionlistDisplayModes(int raw) {
21
- List<ActionListDisplayMode> modes = [];
21
+ final modes = List<ActionListDisplayMode>();
22
23
if (raw == 1 || raw - 10 == 1) {
24
modes.add(ActionListDisplayMode.trades);
lib/src/stores/action_list/action_list_store.dart
+33
-33
@@ -28,8 +28,36 @@ part 'action_list_store.g.dart';
28
class ActionListStore = ActionListBase with _$ActionListStore;
29
30
abstract class ActionListBase with Store {
31
+ ActionListBase(
32
+ {@required WalletService walletService,
33
+ @required SettingsStore settingsStore,
34
+ @required PriceStore priceStore,
35
+ @required this.transactionFilterStore,
36
+ @required this.tradeFilterStore,
37
+ @required this.transactionDescriptions,
38
+ @required this.tradesSource}) {
39
+ trades = List<TradeListItem>();
40
+ _transactions = List<TransactionListItem>();
41
+ _walletService = walletService;
42
+ _settingsStore = settingsStore;
43
+ _priceStore = priceStore;
44
+
45
+ if (walletService.currentWallet != null) {
46
+ _onWalletChanged(walletService.currentWallet);
47
+ }
48
+
49
+ _onWalletChangeSubscription =
50
+ walletService.onWalletChange.listen(_onWalletChanged);
51
+
52
+ _onTransactionDescriptions = transactionDescriptions
53
+ .watch()
54
+ .listen((_) async => await _updateTransactionsList());
55
+
56
+ updateTradeList();
57
+ }
58
+
59
static List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
32
- var formattedList = List<ActionListItem>();
60
+ final formattedList = List<ActionListItem>();
61
DateTime lastDate;
62
items.sort((a, b) => b.date.compareTo(a.date));
63
@@ -84,7 +112,7 @@ abstract class ActionListBase with Store {
112
113
@computed
114
List<ActionListItem> get items {
87
- var _items = List<ActionListItem>();
115
+ final _items = List<ActionListItem>();
116
117
if (_settingsStore.actionlistDisplayMode
118
.contains(ActionListDisplayMode.transactions)) {
@@ -118,34 +146,6 @@ abstract class ActionListBase with Store {
146
StreamSubscription<Account> _onAccountChangeSubscription;
147
StreamSubscription<BoxEvent> _onTransactionDescriptions;
148
121
- ActionListBase(
122
- {@required WalletService walletService,
123
- @required SettingsStore settingsStore,
124
- @required PriceStore priceStore,
125
- @required this.transactionFilterStore,
126
- @required this.tradeFilterStore,
127
- @required this.transactionDescriptions,
128
- @required this.tradesSource}) {
129
- trades = List<TradeListItem>();
130
- _transactions = List<TransactionListItem>();
131
- _walletService = walletService;
132
- _settingsStore = settingsStore;
133
- _priceStore = priceStore;
134
-
135
- if (walletService.currentWallet != null) {
136
- _onWalletChanged(walletService.currentWallet);
137
- }
138
-
139
- _onWalletChangeSubscription =
140
- walletService.onWalletChange.listen(_onWalletChanged);
141
-
142
- _onTransactionDescriptions = transactionDescriptions
143
- .watch()
144
- .listen((_) async => await _updateTransactionsList());
145
-
146
- updateTradeList();
147
- }
148
-
149
@override
150
void dispose() {
151
if (_onTransactionsChangeSubscription != null) {
@@ -174,11 +174,11 @@ abstract class ActionListBase with Store {
174
175
Future _onWalletChanged(Wallet wallet) async {
176
if (_onTransactionsChangeSubscription != null) {
177
- _onTransactionsChangeSubscription.cancel();
177
+ await _onTransactionsChangeSubscription.cancel();
178
}
179
180
if (_onAccountChangeSubscription != null) {
181
- _onAccountChangeSubscription.cancel();
181
+ await _onAccountChangeSubscription.cancel();
182
}
183
184
_history = wallet.getHistory();
@@ -199,7 +199,7 @@ abstract class ActionListBase with Store {
199
Future _setTransactions(List<TransactionInfo> transactions) async {
200
final wallet = _walletService.currentWallet;
201
List<TransactionInfo> sortedTransactions = transactions.map((transaction) {
202
- if (transactionDescriptions.values.length > 0) {
202
+ if (transactionDescriptions.values.isNotEmpty) {
203
final description = transactionDescriptions.values.firstWhere(
204
(desc) => desc.id == transaction.id,
205
orElse: () => null);
lib/src/stores/action_list/date_section_item.dart
+3
-2
@@ -1,7 +1,8 @@
1
import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
2
3
class DateSectionItem extends ActionListItem {
4
- final DateTime date;
5
-
4
DateSectionItem(this.date);
5
+
6
+ @override
7
+ final DateTime date;
8
}
\ No newline at end of file
lib/src/stores/action_list/trade_filter_store.dart
+6
-7
@@ -8,6 +8,11 @@ part 'trade_filter_store.g.dart';
8
class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore;
9
10
abstract class TradeFilterStoreBase with Store {
11
+ TradeFilterStoreBase(
12
+ {this.displayXMRTO = true,
13
+ this.displayChangeNow = true,
14
+ this.walletStore});
15
+
16
@observable
17
bool displayXMRTO;
18
@@ -16,11 +21,6 @@ abstract class TradeFilterStoreBase with Store {
21
22
WalletStore walletStore;
23
19
- TradeFilterStoreBase(
20
- {this.displayXMRTO = true,
21
- this.displayChangeNow = true,
22
- this.walletStore});
23
-
24
@action
25
void toggleDisplayExchange(ExchangeProviderDescription provider) {
26
switch (provider) {
@@ -34,9 +34,8 @@ abstract class TradeFilterStoreBase with Store {
34
}
35
36
List<TradeListItem> filtered({List<TradeListItem> trades}) {
37
- List<TradeListItem> _trades =
37
+ final _trades =
38
trades.where((item) => item.trade.walletId == walletStore.id).toList();
39
-
39
final needToFilter = !displayChangeNow || !displayXMRTO;
40
41
return needToFilter
lib/src/stores/action_list/trade_list_item.dart
+4
-3
@@ -2,9 +2,10 @@ import 'package:cake_wallet/src/domain/exchange/trade.dart';
2
import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
3
4
class TradeListItem extends ActionListItem {
5
+ TradeListItem({this.trade});
6
+
7
final Trade trade;
8
9
+ @override
10
DateTime get date => trade.createdAt;
8
-
9
- TradeListItem({this.trade});
10
-}
\ No newline at end of file
11
+}
lib/src/stores/action_list/transaction_filter_store.dart
+3
-3
@@ -8,6 +8,9 @@ class TransactionFilterStore = TransactionFilterStoreBase
8
with _$TransactionFilterStore;
9
10
abstract class TransactionFilterStoreBase with Store {
11
+ TransactionFilterStoreBase(
12
+ {this.displayIncoming = true, this.displayOutgoing = true});
13
+
14
@observable
15
bool displayIncoming;
16
@@ -20,9 +23,6 @@ abstract class TransactionFilterStoreBase with Store {
23
@observable
24
DateTime endDate;
25
23
- TransactionFilterStoreBase(
24
- {this.displayIncoming = true, this.displayOutgoing = true});
25
-
26
@action
27
void toggleIncoming() => displayIncoming = !displayIncoming;
28
lib/src/stores/action_list/transaction_list_item.dart
+3
-2
@@ -2,9 +2,10 @@ import 'package:cake_wallet/src/domain/common/transaction_info.dart';
2
import 'package:cake_wallet/src/stores/action_list/action_list_item.dart';
3
4
class TransactionListItem extends ActionListItem {
5
+ TransactionListItem({this.transaction});
6
+
7
final TransactionInfo transaction;
8
9
+ @override
10
DateTime get date => transaction.date;
8
-
9
- TransactionListItem({this.transaction});
11
}
\ No newline at end of file
lib/src/stores/address_book/address_book_store.dart
+10
-8
@@ -10,6 +10,10 @@ part 'address_book_store.g.dart';
10
class AddressBookStore = AddressBookStoreBase with _$AddressBookStore;
11
12
abstract class AddressBookStoreBase with Store {
13
+ AddressBookStoreBase({@required this.contacts}) {
14
+ updateContactList();
15
+ }
16
+
17
@observable
18
List<Contact> contactList;
19
@@ -21,10 +25,6 @@ abstract class AddressBookStoreBase with Store {
25
26
Box<Contact> contacts;
27
24
- AddressBookStoreBase({@required this.contacts}) {
25
- updateContactList();
26
- }
27
-
28
@action
29
Future add({Contact contact}) async => contacts.add(contact);
30
@@ -38,17 +38,18 @@ abstract class AddressBookStoreBase with Store {
38
Future delete({Contact contact}) async => await contact.delete();
39
40
void validateContactName(String value) {
41
- String p = '''^[^`,'"]{1,32}\$''';
42
- RegExp regExp = new RegExp(p);
41
+ const pattern = '''^[^`,'"]{1,32}\$''';
42
+ final regExp = RegExp(pattern);
43
isValid = regExp.hasMatch(value);
44
errorMessage = isValid ? null : S.current.error_text_contact_name;
45
}
46
47
void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
48
// XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
49
- String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
50
- RegExp regExp = new RegExp(p);
49
+ const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
50
+ final regExp = RegExp(pattern);
51
isValid = regExp.hasMatch(value);
52
+
53
if (isValid && cryptoCurrency != null) {
54
switch (cryptoCurrency.toString()) {
55
case 'XMR':
@@ -70,6 +71,7 @@ abstract class AddressBookStoreBase with Store {
71
isValid = (value.length == 34);
72
}
73
}
74
+
75
errorMessage = isValid ? null : S.current.error_text_address;
76
}
77
}
lib/src/stores/auth/auth_state.dart
+4
-4
@@ -7,14 +7,14 @@ class AuthenticationInProgress extends AuthState {}
7
class AuthenticatedSuccessfully extends AuthState {}
8
9
class AuthenticationFailure extends AuthState {
10
- final String error;
11
-
10
AuthenticationFailure({this.error});
13
-}
11
15
-class AuthenticationBanned extends AuthState {
12
final String error;
13
+}
14
15
+class AuthenticationBanned extends AuthState {
16
AuthenticationBanned({this.error});
17
+
18
+ final String error;
19
}
20
lib/src/stores/auth/auth_store.dart
+8
-8
@@ -12,6 +12,14 @@ part 'auth_store.g.dart';
12
class AuthStore = AuthStoreBase with _$AuthStore;
13
14
abstract class AuthStoreBase with Store {
15
+ AuthStoreBase(
16
+ {@required this.userService,
17
+ @required this.walletService,
18
+ @required this.sharedPreferences}) {
19
+ state = AuthenticationStateInitial();
20
+ _failureCounter = 0;
21
+ }
22
+
23
static const maxFailedLogins = 3;
24
static const banTimeout = 180; // 3 mins
25
final banTimeoutKey = S.current.auth_store_ban_timeout;
@@ -27,14 +35,6 @@ abstract class AuthStoreBase with Store {
35
@observable
36
int _failureCounter;
37
30
- AuthStoreBase(
31
- {@required this.userService,
32
- @required this.walletService,
33
- @required this.sharedPreferences}) {
34
- state = AuthenticationStateInitial();
35
- _failureCounter = 0;
36
- }
37
-
38
@action
39
Future auth({String password}) async {
40
state = AuthenticationStateInitial();
lib/src/stores/authentication/authentication_store.dart
+4
-4
@@ -21,6 +21,10 @@ enum AuthenticationState {
21
}
22
23
abstract class AuthenticationStoreBase with Store {
24
+ AuthenticationStoreBase({@required this.userService}) {
25
+ state = AuthenticationState.uninitialized;
26
+ }
27
+
28
final UserService userService;
29
30
@observable
@@ -29,10 +33,6 @@ abstract class AuthenticationStoreBase with Store {
33
@observable
34
String errorMessage;
35
32
- AuthenticationStoreBase({@required this.userService}) {
33
- state = AuthenticationState.uninitialized;
34
- }
35
-
36
Future started() async {
37
final canAuth = await userService.canAuthenticate();
38
state = canAuth ? AuthenticationState.allowed : AuthenticationState.denied;
lib/src/stores/balance/balance_store.dart
+22
-22
@@ -15,6 +15,27 @@ part 'balance_store.g.dart';
15
class BalanceStore = BalanceStoreBase with _$BalanceStore;
16
17
abstract class BalanceStoreBase with Store {
18
+ BalanceStoreBase(
19
+ {String fullBalance = '0.0',
20
+ String unlockedBalance = '0.0',
21
+ @required WalletService walletService,
22
+ @required SettingsStore settingsStore,
23
+ @required PriceStore priceStore}) {
24
+ fullBalance = fullBalance;
25
+ unlockedBalance = unlockedBalance;
26
+ isReversing = false;
27
+ _walletService = walletService;
28
+ _settingsStore = settingsStore;
29
+ _priceStore = priceStore;
30
+
31
+ if (_walletService.currentWallet != null) {
32
+ _onWalletChanged(_walletService.currentWallet);
33
+ }
34
+
35
+ _onWalletChangeSubscription = _walletService.onWalletChange
36
+ .listen((wallet) => _onWalletChanged(wallet));
37
+ }
38
+
39
@observable
40
String fullBalance;
41
@@ -54,27 +75,6 @@ abstract class BalanceStoreBase with Store {
75
SettingsStore _settingsStore;
76
PriceStore _priceStore;
77
57
- BalanceStoreBase(
58
- {String fullBalance = '0.0',
59
- String unlockedBalance = '0.0',
60
- @required WalletService walletService,
61
- @required SettingsStore settingsStore,
62
- @required PriceStore priceStore}) {
63
- fullBalance = fullBalance;
64
- unlockedBalance = unlockedBalance;
65
- isReversing = false;
66
- _walletService = walletService;
67
- _settingsStore = settingsStore;
68
- _priceStore = priceStore;
69
-
70
- if (_walletService.currentWallet != null) {
71
- _onWalletChanged(_walletService.currentWallet);
72
- }
73
-
74
- _onWalletChangeSubscription = _walletService.onWalletChange
75
- .listen((wallet) => _onWalletChanged(wallet));
76
- }
77
-
78
@override
79
void dispose() {
80
_onWalletChangeSubscription.cancel();
@@ -100,7 +100,7 @@ abstract class BalanceStoreBase with Store {
100
101
Future _onWalletChanged(Wallet wallet) async {
102
if (_onBalanceChangeSubscription != null) {
103
- _onBalanceChangeSubscription.cancel();
103
+ await _onBalanceChangeSubscription.cancel();
104
}
105
106
_onBalanceChangeSubscription = _walletService.onBalanceChange
lib/src/stores/exchange/exchange_store.dart
+29
-30
@@ -19,6 +19,21 @@ part 'exchange_store.g.dart';
19
class ExchangeStore = ExchangeStoreBase with _$ExchangeStore;
20
21
abstract class ExchangeStoreBase with Store {
22
+ ExchangeStoreBase(
23
+ {@required ExchangeProvider initialProvider,
24
+ @required CryptoCurrency initialDepositCurrency,
25
+ @required CryptoCurrency initialReceiveCurrency,
26
+ @required this.providerList,
27
+ @required this.trades,
28
+ @required this.walletStore}) {
29
+ provider = initialProvider;
30
+ depositCurrency = initialDepositCurrency;
31
+ receiveCurrency = initialReceiveCurrency;
32
+ limitsState = LimitsInitialState();
33
+ tradeState = ExchangeTradeStateInitial();
34
+ loadLimits();
35
+ }
36
+
37
@observable
38
ExchangeProvider provider;
39
@@ -57,21 +72,6 @@ abstract class ExchangeStoreBase with Store {
72
73
WalletStore walletStore;
74
60
- ExchangeStoreBase(
61
- {@required ExchangeProvider initialProvider,
62
- @required CryptoCurrency initialDepositCurrency,
63
- @required CryptoCurrency initialReceiveCurrency,
64
- @required this.providerList,
65
- @required this.trades,
66
- @required this.walletStore}) {
67
- provider = initialProvider;
68
- depositCurrency = initialDepositCurrency;
69
- receiveCurrency = initialReceiveCurrency;
70
- limitsState = LimitsInitialState();
71
- tradeState = ExchangeTradeStateInitial();
72
- loadLimits();
73
- }
74
-
75
@action
76
void changeProvider({ExchangeProvider provider}) {
77
this.provider = provider;
@@ -190,12 +190,10 @@ abstract class ExchangeStoreBase with Store {
190
List<ExchangeProvider> _providersForPair(
191
{CryptoCurrency from, CryptoCurrency to}) {
192
final providers = providerList
193
- .where((provider) =>
194
- provider.pairList
195
- .where((pair) =>
196
- pair.from == depositCurrency && pair.to == receiveCurrency)
197
- .length >
198
- 0)
193
+ .where((provider) => provider.pairList
194
+ .where((pair) =>
195
+ pair.from == depositCurrency && pair.to == receiveCurrency)
196
+ .isNotEmpty)
197
.toList();
198
199
return providers;
@@ -203,10 +201,9 @@ abstract class ExchangeStoreBase with Store {
201
202
void _onPairChange() {
203
final isPairExist = provider.pairList
206
- .where((pair) =>
207
- pair.from == depositCurrency && pair.to == receiveCurrency)
208
- .length >
209
- 0;
204
+ .where((pair) =>
205
+ pair.from == depositCurrency && pair.to == receiveCurrency)
206
+ .isNotEmpty;
207
208
if (!isPairExist) {
209
final provider =
@@ -225,14 +222,15 @@ abstract class ExchangeStoreBase with Store {
222
223
ExchangeProvider _providerForPair({CryptoCurrency from, CryptoCurrency to}) {
224
final providers = _providersForPair(from: from, to: to);
228
- return providers.length > 0 ? providers[0] : null;
225
+ return providers.isNotEmpty ? providers[0] : null;
226
}
227
228
void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
229
// XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
233
- String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
234
- RegExp regExp = new RegExp(p);
230
+ const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
231
+ final regExp = RegExp(pattern);
232
isValid = regExp.hasMatch(value);
233
+
234
if (isValid && cryptoCurrency != null) {
235
switch (cryptoCurrency.toString()) {
236
case 'XMR':
@@ -254,12 +252,13 @@ abstract class ExchangeStoreBase with Store {
252
isValid = (value.length == 34);
253
}
254
}
255
+
256
errorMessage = isValid ? null : S.current.error_text_address;
257
}
258
259
void validateCryptoCurrency(String value) {
261
- String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
262
- RegExp regExp = new RegExp(p);
260
+ const pattern = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
261
+ final regExp = RegExp(pattern);
262
isValid = regExp.hasMatch(value);
263
errorMessage = isValid ? null : S.current.error_text_crypto_currency;
264
}
lib/src/stores/exchange/exchange_trade_state.dart
+4
-4
@@ -8,13 +8,13 @@ class ExchangeTradeStateInitial extends ExchangeTradeState {}
8
class TradeIsCreating extends ExchangeTradeState {}
9
10
class TradeIsCreatedSuccessfully extends ExchangeTradeState {
11
- final Trade trade;
12
-
11
TradeIsCreatedSuccessfully({@required this.trade});
12
+
13
+ final Trade trade;
14
}
15
16
class TradeIsCreatedFailure extends ExchangeTradeState {
17
- final String error;
18
-
17
TradeIsCreatedFailure({@required this.error});
18
+
19
+ final String error;
20
}
\ No newline at end of file
lib/src/stores/exchange/limits_state.dart
+4
-4
@@ -8,13 +8,13 @@ class LimitsInitialState extends LimitsState {}
8
class LimitsIsLoading extends LimitsState {}
9
10
class LimitsLoadedSuccessfully extends LimitsState {
11
- final Limits limits;
12
-
11
LimitsLoadedSuccessfully({@required this.limits});
12
+
13
+ final Limits limits;
14
}
15
16
class LimitsLoadedFailure extends LimitsState {
17
- final String error;
18
-
17
LimitsLoadedFailure({@required this.error});
18
+
19
+ final String error;
20
}
lib/src/stores/exchange_trade/exchange_trade_store.dart
+18
-16
@@ -13,18 +13,10 @@ part 'exchange_trade_store.g.dart';
13
class ExchangeTradeStore = ExchangeTradeStoreBase with _$ExchangeTradeStore;
14
15
abstract class ExchangeTradeStoreBase with Store {
16
- @observable
17
- Trade trade;
18
-
19
- @observable
20
- bool isSendable;
21
-
22
- ExchangeProvider _provider;
23
-
24
- Timer _timer;
25
-
26
- ExchangeTradeStoreBase({@required this.trade, @required WalletStore walletStore}) {
27
- isSendable = trade.from == walletStore.type || trade.provider == ExchangeProviderDescription.xmrto;
16
+ ExchangeTradeStoreBase(
17
+ {@required this.trade, @required WalletStore walletStore}) {
18
+ isSendable = trade.from == walletStore.type ||
19
+ trade.provider == ExchangeProviderDescription.xmrto;
20
21
switch (trade.provider) {
22
case ExchangeProviderDescription.xmrto:
@@ -34,25 +26,35 @@ abstract class ExchangeTradeStoreBase with Store {
26
_provider = ChangeNowExchangeProvider();
27
break;
28
}
37
-
29
+
30
_updateTrade();
31
_timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade());
32
}
33
34
+ @observable
35
+ Trade trade;
36
+
37
+ @observable
38
+ bool isSendable;
39
+
40
+ ExchangeProvider _provider;
41
+
42
+ Timer _timer;
43
+
44
@override
45
void dispose() {
46
super.dispose();
45
-
47
+
48
if (_timer != null) {
49
_timer.cancel();
50
}
51
}
52
53
@action
52
- Future _updateTrade() async {
54
+ Future<void> _updateTrade() async {
55
try {
56
final updatedTrade = await _provider.findTradeById(id: trade.id);
55
-
57
+
58
if (updatedTrade.createdAt == null && trade.createdAt != null) {
59
updatedTrade.createdAt = trade.createdAt;
60
}
lib/src/stores/login/login_store.dart
+7
-7
@@ -14,25 +14,25 @@ class LoadingCurrentWallet extends LoginState {}
14
class LoadedCurrentWalletSuccessfully extends LoginState {}
15
16
class LoadedCurrentWalletFailure extends LoginState {
17
- final String errorMessage;
18
-
17
LoadedCurrentWalletFailure({this.errorMessage});
18
+
19
+ final String errorMessage;
20
}
21
22
class LoginStore = LoginStoreBase with _$LoginStore;
23
24
abstract class LoginStoreBase with Store {
25
+ LoginStoreBase(
26
+ {@required this.sharedPreferences, @required this.walletsService}) {
27
+ state = InitialLoginState();
28
+ }
29
+
30
final SharedPreferences sharedPreferences;
31
final WalletListService walletsService;
32
33
@observable
34
LoginState state;
35
31
- LoginStoreBase(
32
- {@required this.sharedPreferences, @required this.walletsService}) {
33
- state = InitialLoginState();
34
- }
35
-
36
@action
37
Future loadCurrentWallet() async {
38
state = InitialLoginState();
lib/src/stores/node_list/node_list_store.dart
+16
-13
@@ -10,6 +10,12 @@ part 'node_list_store.g.dart';
10
class NodeListStore = NodeListBase with _$NodeListStore;
11
12
abstract class NodeListBase with Store {
13
+ NodeListBase({this.nodesSource}) {
14
+ nodes = ObservableList<Node>();
15
+ _onNodesChangeSubscription = nodesSource.watch().listen((e) => update());
16
+ update();
17
+ }
18
+
19
@observable
20
ObservableList<Node> nodes;
21
@@ -23,12 +29,6 @@ abstract class NodeListBase with Store {
29
30
StreamSubscription<BoxEvent> _onNodesChangeSubscription;
31
26
- NodeListBase({this.nodesSource}) {
27
- nodes = ObservableList<Node>();
28
- _onNodesChangeSubscription = nodesSource.watch().listen((e) => update());
29
- update();
30
- }
31
-
32
@override
33
void dispose() {
34
super.dispose();
@@ -39,7 +39,7 @@ abstract class NodeListBase with Store {
39
}
40
41
@action
42
- update() async =>
42
+ void update() =>
43
nodes.replaceRange(0, nodes.length, nodesSource.values.toList());
44
45
@action
@@ -71,25 +71,28 @@ abstract class NodeListBase with Store {
71
}
72
73
void validateNodeAddress(String value) {
74
- String p =
74
+ const pattern =
75
'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\$';
76
- RegExp regExp = new RegExp(p);
76
+ final regExp = RegExp(pattern);
77
isValid = regExp.hasMatch(value);
78
errorMessage = isValid ? null : S.current.error_text_node_address;
79
}
80
81
void validateNodePort(String value) {
82
- String p = '^[0-9]{1,5}';
83
- RegExp regExp = new RegExp(p);
82
+ const pattern = '^[0-9]{1,5}';
83
+ final regExp = RegExp(pattern);
84
+
85
if (regExp.hasMatch(value)) {
86
try {
86
- int intValue = int.parse(value);
87
+ final intValue = int.parse(value);
88
isValid = (intValue >= 0 && intValue <= 65535);
89
} catch (e) {
90
isValid = false;
91
}
91
- } else
92
+ } else {
93
isValid = false;
94
+ }
95
+
96
errorMessage = isValid ? null : S.current.error_text_node_port;
97
}
98
}
lib/src/stores/price/price_store.dart
+4
-3
@@ -8,6 +8,8 @@ part 'price_store.g.dart';
8
class PriceStore = PriceStoreBase with _$PriceStore;
9
10
abstract class PriceStoreBase with Store {
11
+ PriceStoreBase() : prices = ObservableMap();
12
+
13
static String generateSymbolForPair(
14
{FiatCurrency fiat, CryptoCurrency crypto}) =>
15
crypto.toString().toUpperCase() + fiat.toString().toUpperCase();
@@ -15,8 +17,6 @@ abstract class PriceStoreBase with Store {
17
@observable
18
ObservableMap<String, double> prices;
19
18
- PriceStoreBase() : prices = ObservableMap();
19
-
20
@action
21
Future updatePrice({FiatCurrency fiat, CryptoCurrency crypto}) async {
22
final symbol = generateSymbolForPair(fiat: fiat, crypto: crypto);
@@ -25,7 +25,8 @@ abstract class PriceStoreBase with Store {
25
}
26
27
@action
28
- changePriceForPair({FiatCurrency fiat, CryptoCurrency crypto, double price}) {
28
+ void changePriceForPair(
29
+ {FiatCurrency fiat, CryptoCurrency crypto, double price}) {
30
final symbol = generateSymbolForPair(fiat: fiat, crypto: crypto);
31
prices[symbol] = price;
32
}
lib/src/stores/rescan/rescan_wallet_store.dart
+6
-8
@@ -6,21 +6,19 @@ part 'rescan_wallet_store.g.dart';
6
7
class RescanWalletStore = RescanWalletStoreBase with _$RescanWalletStore;
8
9
-enum RescanWalletState {
10
- rescaning, none
11
-}
9
+enum RescanWalletState { rescaning, none }
10
11
abstract class RescanWalletStoreBase with Store {
14
- @observable
15
- RescanWalletState state;
16
-
17
- WalletService _walletService;
18
-
12
RescanWalletStoreBase({@required WalletService walletService}) {
13
_walletService = walletService;
14
state = RescanWalletState.none;
15
}
16
17
+ @observable
18
+ RescanWalletState state;
19
+
20
+ WalletService _walletService;
21
+
22
@action
23
Future rescanCurrentWallet({int restoreHeight}) async {
24
state = RescanWalletState.rescaning;
lib/src/stores/send/send_store.dart
+44
-34
@@ -17,6 +17,23 @@ part 'send_store.g.dart';
17
class SendStore = SendStoreBase with _$SendStore;
18
19
abstract class SendStoreBase with Store {
20
+ SendStoreBase(
21
+ {@required this.walletService,
22
+ this.settingsStore,
23
+ this.transactionDescriptions,
24
+ this.priceStore}) {
25
+ state = SendingStateInitial();
26
+ _pendingTransaction = null;
27
+ _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
28
+ _fiatNumberFormat = NumberFormat()..maximumFractionDigits = 2;
29
+
30
+ reaction((_) => this.state, (SendingState state) async {
31
+ if (state is TransactionCreatedSuccessfully) {
32
+ await commitTransaction();
33
+ }
34
+ });
35
+ }
36
+
37
WalletService walletService;
38
SettingsStore settingsStore;
39
PriceStore priceStore;
@@ -43,23 +60,6 @@ abstract class SendStoreBase with Store {
60
NumberFormat _fiatNumberFormat;
61
String _lastRecipientAddress;
62
46
- SendStoreBase(
47
- {@required this.walletService,
48
- this.settingsStore,
49
- this.transactionDescriptions,
50
- this.priceStore}) {
51
- state = SendingStateInitial();
52
- _pendingTransaction = null;
53
- _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
54
- _fiatNumberFormat = NumberFormat()..maximumFractionDigits = 2;
55
-
56
- reaction((_) => this.state, (state) async {
57
- if (state is TransactionCreatedSuccessfully) {
58
- commitTransaction();
59
- }
60
- });
61
- }
62
-
63
@action
64
Future createTransaction(
65
{String address, String paymentId, String amount}) async {
@@ -160,9 +160,10 @@ abstract class SendStoreBase with Store {
160
161
void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
162
// XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
163
- String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
164
- RegExp regExp = new RegExp(p);
163
+ const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
164
+ final regExp = RegExp(pattern);
165
isValid = value == null ? false : regExp.hasMatch(value);
166
+
167
if (isValid && cryptoCurrency != null) {
168
switch (cryptoCurrency.toString()) {
169
case 'XMR':
@@ -184,6 +185,7 @@ abstract class SendStoreBase with Store {
185
isValid = (value.length == 34);
186
}
187
}
188
+
189
errorMessage = isValid ? null : S.current.error_text_address;
190
}
191
@@ -191,52 +193,60 @@ abstract class SendStoreBase with Store {
193
if (value.isEmpty) {
194
isValid = true;
195
} else {
194
- String p = '^[A-Fa-f0-9]{16,64}\$';
195
- RegExp regExp = new RegExp(p);
196
+ const pattern = '^[A-Fa-f0-9]{16,64}\$';
197
+ final regExp = RegExp(pattern);
198
isValid = regExp.hasMatch(value);
199
}
200
+
201
errorMessage = isValid ? null : S.current.error_text_payment_id;
202
}
203
204
void validateXMR(String value, String availableBalance) {
205
const double maxValue = 18446744.073709551616;
203
- String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$|ALL';
204
- RegExp regExp = new RegExp(p);
206
+ const pattern = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$|ALL';
207
+ final regExp = RegExp(pattern);
208
+
209
if (regExp.hasMatch(value)) {
206
- if (value == 'ALL')
210
+ if (value == 'ALL') {
211
isValid = true;
208
- else {
212
+ } else {
213
try {
210
- double dValue = double.parse(value);
211
- double maxAvailable = double.parse(availableBalance);
214
+ final dValue = double.parse(value);
215
+ final maxAvailable = double.parse(availableBalance);
216
isValid =
217
(dValue <= maxAvailable && dValue <= maxValue && dValue > 0);
218
} catch (e) {
219
isValid = false;
220
}
221
}
218
- } else
222
+ } else {
223
isValid = false;
224
+ }
225
+
226
errorMessage = isValid ? null : S.current.error_text_xmr;
227
}
228
229
void validateFiat(String value, {double maxValue}) {
230
const double minValue = 0.01;
225
- if (value.isEmpty && cryptoAmount == 'ALL')
231
+
232
+ if (value.isEmpty && cryptoAmount == 'ALL') {
233
isValid = true;
227
- else {
228
- String p = '^([0-9]+([.][0-9]{0,2})?|[.][0-9]{1,2})\$';
229
- RegExp regExp = new RegExp(p);
234
+ } else {
235
+ const pattern = '^([0-9]+([.][0-9]{0,2})?|[.][0-9]{1,2})\$';
236
+ final regExp = RegExp(pattern);
237
+
238
if (regExp.hasMatch(value)) {
239
try {
232
- double dValue = double.parse(value);
240
+ final dValue = double.parse(value);
241
isValid = (dValue >= minValue && dValue <= maxValue);
242
} catch (e) {
243
isValid = false;
244
}
237
- } else
245
+ } else {
246
isValid = false;
247
+ }
248
}
249
+
250
errorMessage = isValid
251
? null
252
: "Value of amount can't exceed available balance.\n"
lib/src/stores/send/sending_state.dart
+2
-2
@@ -13,7 +13,7 @@ class TransactionCommiting extends SendingState {}
13
class TransactionCommitted extends SendingState {}
14
15
class SendingFailed extends SendingState {
16
- String error;
17
-
16
SendingFailed({@required this.error});
17
+
18
+ String error;
19
}
lib/src/stores/settings/settings_store.dart
+33
-33
@@ -17,6 +17,36 @@ part 'settings_store.g.dart';
17
class SettingsStore = SettingsStoreBase with _$SettingsStore;
18
19
abstract class SettingsStoreBase with Store {
20
+ SettingsStoreBase(
21
+ {@required SharedPreferences sharedPreferences,
22
+ @required Box<Node> nodes,
23
+ @required FiatCurrency initialFiatCurrency,
24
+ @required TransactionPriority initialTransactionPriority,
25
+ @required BalanceDisplayMode initialBalanceDisplayMode,
26
+ @required bool initialSaveRecipientAddress,
27
+ @required bool initialAllowBiometricalAuthentication,
28
+ @required bool initialDarkTheme,
29
+ this.actionlistDisplayMode,
30
+ @required int initialPinLength,
31
+ @required String initialLanguageCode}) {
32
+ fiatCurrency = initialFiatCurrency;
33
+ transactionPriority = initialTransactionPriority;
34
+ balanceDisplayMode = initialBalanceDisplayMode;
35
+ shouldSaveRecipientAddress = initialSaveRecipientAddress;
36
+ _sharedPreferences = sharedPreferences;
37
+ _nodes = nodes;
38
+ allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
39
+ isDarkTheme = initialDarkTheme;
40
+ defaultPinLength = initialPinLength;
41
+ languageCode = initialLanguageCode;
42
+ itemHeaders = Map();
43
+
44
+ actionlistDisplayMode.observe(
45
+ (dynamic _) => _sharedPreferences.setInt(displayActionListModeKey,
46
+ serializeActionlistDisplayModes(actionlistDisplayMode)),
47
+ fireImmediately: false);
48
+ }
49
+
50
static const currentNodeIdKey = 'current_node_id';
51
static const currentFiatCurrencyKey = 'current_fiat_currency';
52
static const currentTransactionPriorityKey = 'current_fee_priority';
@@ -113,36 +143,6 @@ abstract class SettingsStoreBase with Store {
143
SharedPreferences _sharedPreferences;
144
Box<Node> _nodes;
145
116
- SettingsStoreBase(
117
- {@required SharedPreferences sharedPreferences,
118
- @required Box<Node> nodes,
119
- @required FiatCurrency initialFiatCurrency,
120
- @required TransactionPriority initialTransactionPriority,
121
- @required BalanceDisplayMode initialBalanceDisplayMode,
122
- @required bool initialSaveRecipientAddress,
123
- @required bool initialAllowBiometricalAuthentication,
124
- @required bool initialDarkTheme,
125
- this.actionlistDisplayMode,
126
- @required int initialPinLength,
127
- @required String initialLanguageCode}) {
128
- fiatCurrency = initialFiatCurrency;
129
- transactionPriority = initialTransactionPriority;
130
- balanceDisplayMode = initialBalanceDisplayMode;
131
- shouldSaveRecipientAddress = initialSaveRecipientAddress;
132
- _sharedPreferences = sharedPreferences;
133
- _nodes = nodes;
134
- allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
135
- isDarkTheme = initialDarkTheme;
136
- defaultPinLength = initialPinLength;
137
- languageCode = initialLanguageCode;
138
- itemHeaders = Map();
139
-
140
- actionlistDisplayMode.observe(
141
- (dynamic _) => _sharedPreferences.setInt(displayActionListModeKey,
142
- serializeActionlistDisplayModes(actionlistDisplayMode)),
143
- fireImmediately: false);
144
- }
145
-
146
@action
147
Future setAllowBiometricalAuthentication(
148
{@required bool allowBiometricalAuthentication}) async {
@@ -168,7 +168,7 @@ abstract class SettingsStoreBase with Store {
168
@action
169
Future setCurrentNode({@required Node node}) async {
170
this.node = node;
171
- await _sharedPreferences.setInt(currentNodeIdKey, node.key);
171
+ await _sharedPreferences.setInt(currentNodeIdKey, node.key as int);
172
}
173
174
@action
@@ -203,7 +203,7 @@ abstract class SettingsStoreBase with Store {
203
}
204
205
Future loadSettings() async => node = await _fetchCurrentNode();
206
-
206
+
207
@action
208
void toggleTransactionsDisplay() =>
209
actionlistDisplayMode.contains(ActionListDisplayMode.transactions)
@@ -239,7 +239,7 @@ abstract class SettingsStoreBase with Store {
239
240
Future<Node> _fetchCurrentNode() async {
241
final id = _sharedPreferences.getInt(currentNodeIdKey);
242
-
242
+
243
return _nodes.get(id);
244
}
245
lib/src/stores/subaddress_creation/subaddress_creation_state.dart
+2
-2
@@ -7,7 +7,7 @@ class SubaddressIsCreating extends SubaddressCreationState {}
7
class SubaddressCreatedSuccessfully extends SubaddressCreationState {}
8
9
class SubaddressCreationFailure extends SubaddressCreationState {
10
- String error;
11
-
10
SubaddressCreationFailure({this.error});
11
+
12
+ String error;
13
}
\ No newline at end of file
lib/src/stores/subaddress_creation/subaddress_creation_store.dart
+18
-17
@@ -15,6 +15,17 @@ class SubadrressCreationStore = SubadrressCreationStoreBase
15
with _$SubadrressCreationStore;
16
17
abstract class SubadrressCreationStoreBase with Store {
18
+ SubadrressCreationStoreBase({@required WalletService walletService}) {
19
+ state = SubaddressCreationStateInitial();
20
+
21
+ if (walletService.currentWallet != null) {
22
+ _onWalletChanged(walletService.currentWallet);
23
+ }
24
+
25
+ _onWalletChangeSubscription =
26
+ walletService.onWalletChange.listen(_onWalletChanged);
27
+ }
28
+
29
SubaddressCreationState state;
30
31
@observable
@@ -28,17 +39,6 @@ abstract class SubadrressCreationStoreBase with Store {
39
StreamSubscription<Account> _onAccountChangeSubscription;
40
Account _account;
41
31
- SubadrressCreationStoreBase({@required WalletService walletService}) {
32
- state = SubaddressCreationStateInitial();
33
-
34
- if (walletService.currentWallet != null) {
35
- _onWalletChanged(walletService.currentWallet);
36
- }
37
-
38
- _onWalletChangeSubscription =
39
- walletService.onWalletChange.listen(_onWalletChanged);
40
- }
41
-
42
@override
43
void dispose() {
44
_onWalletChangeSubscription.cancel();
@@ -50,7 +50,7 @@ abstract class SubadrressCreationStoreBase with Store {
50
super.dispose();
51
}
52
53
- Future add({String label}) async {
53
+ Future<void> add({String label}) async {
54
try {
55
state = SubaddressIsCreating();
56
await _subaddressList.addSubaddress(
@@ -61,14 +61,15 @@ abstract class SubadrressCreationStoreBase with Store {
61
}
62
}
63
64
- Future _onWalletChanged(Wallet wallet) async {
64
+ Future<void> _onWalletChanged(Wallet wallet) async {
65
if (wallet is MoneroWallet) {
66
_account = wallet.account;
67
_subaddressList = wallet.getSubaddress();
68
69
- _onAccountChangeSubscription = wallet.onAccountChange.listen((account) async {
69
+ _onAccountChangeSubscription =
70
+ wallet.onAccountChange.listen((account) async {
71
_account = account;
71
- _subaddressList.update(accountIndex: account.id);
72
+ await _subaddressList.update(accountIndex: account.id);
73
});
74
return;
75
}
@@ -77,8 +78,8 @@ abstract class SubadrressCreationStoreBase with Store {
78
}
79
80
void validateSubaddressName(String value) {
80
- String p = '''^[^`,'"]{1,20}\$''';
81
- RegExp regExp = new RegExp(p);
81
+ const pattern = '''^[^`,'"]{1,20}\$''';
82
+ final regExp = RegExp(pattern);
83
isValid = regExp.hasMatch(value);
84
errorMessage = isValid ? null : S.current.error_text_subaddress_name;
85
}
lib/src/stores/subaddress_list/subaddress_list_store.dart
+14
-13
@@ -13,15 +13,6 @@ part 'subaddress_list_store.g.dart';
13
class SubaddressListStore = SubaddressListStoreBase with _$SubaddressListStore;
14
15
abstract class SubaddressListStoreBase with Store {
16
- @observable
17
- ObservableList<Subaddress> subaddresses;
18
-
19
- SubaddressList _subaddressList;
20
- StreamSubscription<Wallet> _onWalletChangeSubscription;
21
- StreamSubscription<List<Subaddress>> _onSubaddressesChangeSubscription;
22
- StreamSubscription<Account> _onAccountChangeSubscription;
23
- Account _account;
24
-
16
SubaddressListStoreBase({@required WalletService walletService}) {
17
subaddresses = ObservableList<Subaddress>();
18
@@ -33,6 +24,15 @@ abstract class SubaddressListStoreBase with Store {
24
walletService.onWalletChange.listen(_onWalletChanged);
25
}
26
27
+ @observable
28
+ ObservableList<Subaddress> subaddresses;
29
+
30
+ SubaddressList _subaddressList;
31
+ StreamSubscription<Wallet> _onWalletChangeSubscription;
32
+ StreamSubscription<List<Subaddress>> _onSubaddressesChangeSubscription;
33
+ StreamSubscription<Account> _onAccountChangeSubscription;
34
+ Account _account;
35
+
36
@override
37
void dispose() {
38
if (_onSubaddressesChangeSubscription != null) {
@@ -47,14 +47,14 @@ abstract class SubaddressListStoreBase with Store {
47
super.dispose();
48
}
49
50
- Future _updateSubaddressList({int accountIndex}) async {
50
+ Future<void> _updateSubaddressList({int accountIndex}) async {
51
await _subaddressList.refresh(accountIndex: accountIndex);
52
subaddresses = ObservableList.of(_subaddressList.getAll());
53
}
54
55
- Future _onWalletChanged(Wallet wallet) async {
55
+ Future<void> _onWalletChanged(Wallet wallet) async {
56
if (_onSubaddressesChangeSubscription != null) {
57
- _onSubaddressesChangeSubscription.cancel();
57
+ await _onSubaddressesChangeSubscription.cancel();
58
}
59
60
if (wallet is MoneroWallet) {
@@ -64,7 +64,8 @@ abstract class SubaddressListStoreBase with Store {
64
.listen((subaddress) => subaddresses = ObservableList.of(subaddress));
65
await _updateSubaddressList(accountIndex: _account.id);
66
67
- _onAccountChangeSubscription = wallet.onAccountChange.listen((account) async {
67
+ _onAccountChangeSubscription =
68
+ wallet.onAccountChange.listen((account) async {
69
_account = account;
70
await _updateSubaddressList(accountIndex: account.id);
71
});
lib/src/stores/sync/sync_store.dart
+6
-6
@@ -10,12 +10,6 @@ part 'sync_store.g.dart';
10
class SyncStore = SyncStoreBase with _$SyncStore;
11
12
abstract class SyncStoreBase with Store {
13
- @observable
14
- SyncStatus status;
15
-
16
- StreamSubscription<Wallet> _onWalletChangeSubscription;
17
- StreamSubscription<SyncStatus> _onSyncStatusChangeSubscription;
18
-
13
SyncStoreBase(
14
{SyncStatus syncStatus = const NotConnectedSyncStatus(),
15
@required WalletService walletService}) {
@@ -29,6 +23,12 @@ abstract class SyncStoreBase with Store {
23
walletService.onWalletChange.listen(_onWalletChanged);
24
}
25
26
+ @observable
27
+ SyncStatus status;
28
+
29
+ StreamSubscription<Wallet> _onWalletChangeSubscription;
30
+ StreamSubscription<SyncStatus> _onSyncStatusChangeSubscription;
31
+
32
@override
33
void dispose() {
34
if (_onSyncStatusChangeSubscription != null) {
lib/src/stores/user/user_store.dart
+7
-7
@@ -8,6 +8,8 @@ part 'user_store.g.dart';
8
class UserStore = UserStoreBase with _$UserStore;
9
10
abstract class UserStoreBase with Store {
11
+ UserStoreBase({@required this.accountService});
12
+
13
UserService accountService;
14
15
@observable
@@ -16,17 +18,15 @@ abstract class UserStoreBase with Store {
18
@observable
19
String errorMessage;
20
19
- UserStoreBase({@required this.accountService});
20
-
21
@action
22
Future set({String password}) async {
23
state = UserStoreStateInitial();
24
25
try {
26
- await accountService.setPassword(password);
27
- state = PinCodeSetSuccesfully();
28
- } catch(e) {
29
- state = PinCodeSetFailed(error: e.toString());
30
- }
26
+ await accountService.setPassword(password);
27
+ state = PinCodeSetSuccesfully();
28
+ } catch (e) {
29
+ state = PinCodeSetFailed(error: e.toString());
30
+ }
31
}
32
}
lib/src/stores/user/user_store_state.dart
+2
-2
@@ -7,7 +7,7 @@ class UserStoreStateInitial extends UserStoreState {}
7
class PinCodeSetSuccesfully extends UserStoreState {}
8
9
class PinCodeSetFailed extends UserStoreState {
10
- String error;
11
-
10
PinCodeSetFailed({@required this.error});
11
+
12
+ String error;
13
}
lib/src/stores/wallet/wallet_keys_store.dart
+12
-12
@@ -7,18 +7,6 @@ part 'wallet_keys_store.g.dart';
7
class WalletKeysStore = WalletKeysStoreBase with _$WalletKeysStore;
8
9
abstract class WalletKeysStoreBase with Store {
10
- @observable
11
- String publicViewKey;
12
-
13
- @observable
14
- String privateViewKey;
15
-
16
- @observable
17
- String publicSpendKey;
18
-
19
- @observable
20
- String privateSpendKey;
21
-
10
WalletKeysStoreBase({@required WalletService walletService}) {
11
publicViewKey = '';
12
privateViewKey = '';
@@ -34,4 +22,16 @@ abstract class WalletKeysStoreBase with Store {
22
});
23
}
24
}
25
+
26
+ @observable
27
+ String publicViewKey;
28
+
29
+ @observable
30
+ String privateViewKey;
31
+
32
+ @observable
33
+ String publicSpendKey;
34
+
35
+ @observable
36
+ String privateSpendKey;
37
}
lib/src/stores/wallet/wallet_store.dart
+30
-26
@@ -15,6 +15,21 @@ part 'wallet_store.g.dart';
15
class WalletStore = WalletStoreBase with _$WalletStore;
16
17
abstract class WalletStoreBase with Store {
18
+ WalletStoreBase({WalletService walletService, SettingsStore settingsStore}) {
19
+ _walletService = walletService;
20
+ _settingsStore = settingsStore;
21
+ name = '';
22
+ type = CryptoCurrency.xmr;
23
+ amountValue = '';
24
+
25
+ if (_walletService.currentWallet != null) {
26
+ _onWalletChanged(_walletService.currentWallet);
27
+ }
28
+
29
+ _onWalletChangeSubscription = _walletService.onWalletChange
30
+ .listen((wallet) async => await _onWalletChanged(wallet));
31
+ }
32
+
33
@observable
34
String address;
35
@@ -47,22 +62,6 @@ abstract class WalletStoreBase with Store {
62
StreamSubscription<Account> _onAccountChangeSubscription;
63
StreamSubscription<Subaddress> _onSubaddressChangeSubscription;
64
50
-
51
- WalletStoreBase({WalletService walletService, SettingsStore settingsStore}) {
52
- _walletService = walletService;
53
- _settingsStore = settingsStore;
54
- name = '';
55
- type = CryptoCurrency.xmr;
56
- amountValue = '';
57
-
58
- if (_walletService.currentWallet != null) {
59
- _onWalletChanged(_walletService.currentWallet);
60
- }
61
-
62
- _onWalletChangeSubscription = _walletService.onWalletChange
63
- .listen((wallet) async => await _onWalletChanged(wallet));
64
- }
65
-
65
@override
66
void dispose() {
67
if (_onWalletChangeSubscription != null) {
@@ -112,7 +111,8 @@ abstract class WalletStoreBase with Store {
111
Future startSync() async => await _walletService.startSync();
112
113
@action
115
- Future connectToNode({Node node}) async => await _walletService.connectToNode(node: node);
114
+ Future connectToNode({Node node}) async =>
115
+ await _walletService.connectToNode(node: node);
116
117
Future _onWalletChanged(Wallet wallet) async {
118
if (this == null) {
@@ -123,15 +123,16 @@ abstract class WalletStoreBase with Store {
123
wallet.onAddressChange.listen((address) => this.address = address);
124
125
if (wallet is MoneroWallet) {
126
- _onAccountChangeSubscription = wallet.onAccountChange.listen((account) => this.account = account);
127
- _onSubaddressChangeSubscription = wallet.subaddress.listen((subaddress) => this.subaddress = subaddress);
126
+ _onAccountChangeSubscription =
127
+ wallet.onAccountChange.listen((account) => this.account = account);
128
+ _onSubaddressChangeSubscription = wallet.subaddress
129
+ .listen((subaddress) => this.subaddress = subaddress);
130
}
131
}
132
133
@action
132
- onChangedAmountValue(String value) {
133
- amountValue = value.isNotEmpty ? '?tx_amount=' + value : '';
134
- }
134
+ void onChangedAmountValue(String value) =>
135
+ amountValue = value.isNotEmpty ? '?tx_amount=' + value : '';
136
137
@action
138
void validateAmount(String value) {
@@ -140,16 +141,19 @@ abstract class WalletStoreBase with Store {
141
if (value.isEmpty) {
142
isValid = true;
143
} else {
143
- String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
144
- RegExp regExp = new RegExp(p);
144
+ const pattern = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
145
+ final regExp = RegExp(pattern);
146
+
147
if (regExp.hasMatch(value)) {
148
try {
147
- double dValue = double.parse(value);
149
+ final dValue = double.parse(value);
150
isValid = dValue <= maxValue;
151
} catch (e) {
152
isValid = false;
153
}
152
- } else isValid = false;
154
+ } else {
155
+ isValid = false;
156
+ }
157
}
158
159
errorMessage = isValid ? null : S.current.error_text_amount;
lib/src/stores/wallet_creation/wallet_creation_state.dart
+2
-1
@@ -9,6 +9,7 @@ class WalletIsCreating extends WalletCreationState {}
9
class WalletCreatedSuccessfully extends WalletCreationState {}
10
11
class WalletCreationFailure extends WalletCreationState {
12
- String error;
12
WalletCreationFailure({@required this.error});
13
+
14
+ String error;
15
}
\ No newline at end of file
lib/src/stores/wallet_creation/wallet_creation_store.dart
+9
-9
@@ -11,6 +11,13 @@ part 'wallet_creation_store.g.dart';
11
class WalletCreationStore = WalletCreationStoreBase with _$WalletCreationStore;
12
13
abstract class WalletCreationStoreBase with Store {
14
+ WalletCreationStoreBase(
15
+ {@required this.authStore,
16
+ @required this.walletListService,
17
+ @required this.sharedPreferences}) {
18
+ state = WalletCreationStateInitial();
19
+ }
20
+
21
final AuthenticationStore authStore;
22
final WalletListService walletListService;
23
final SharedPreferences sharedPreferences;
@@ -24,13 +31,6 @@ abstract class WalletCreationStoreBase with Store {
31
@observable
32
bool isValid;
33
27
- WalletCreationStoreBase(
28
- {@required this.authStore,
29
- @required this.walletListService,
30
- @required this.sharedPreferences}) {
31
- state = WalletCreationStateInitial();
32
- }
33
-
34
@action
35
Future create({String name}) async {
36
state = WalletCreationStateInitial();
@@ -46,8 +46,8 @@ abstract class WalletCreationStoreBase with Store {
46
}
47
48
void validateWalletName(String value) {
49
- String p = '^[a-zA-Z0-9_]{1,15}\$';
50
- RegExp regExp = new RegExp(p);
49
+ const pattern = '^[a-zA-Z0-9_]{1,15}\$';
50
+ final regExp = RegExp(pattern);
51
isValid = regExp.hasMatch(value);
52
errorMessage = isValid ? null : S.current.error_text_wallet_name;
53
}
lib/src/stores/wallet_list/wallet_list_store.dart
+11
-12
@@ -9,12 +9,6 @@ part 'wallet_list_store.g.dart';
9
class WalletListStore = WalletListStoreBase with _$WalletListStore;
10
11
abstract class WalletListStoreBase with Store {
12
- @observable
13
- List<WalletDescription> wallets;
14
-
15
- WalletListService _walletListService;
16
- WalletService _walletService;
17
-
12
WalletListStoreBase(
13
{@required WalletListService walletListService,
14
@required WalletService walletService}) {
@@ -24,22 +18,27 @@ abstract class WalletListStoreBase with Store {
18
walletListService.getAll().then((walletList) => wallets = walletList);
19
}
20
27
- bool isCurrentWallet(WalletDescription wallet) {
28
- return _walletService.description?.name == wallet.name;
29
- }
21
+ @observable
22
+ List<WalletDescription> wallets;
23
+
24
+ WalletListService _walletListService;
25
+ WalletService _walletService;
26
+
27
+ bool isCurrentWallet(WalletDescription wallet) =>
28
+ _walletService.description?.name == wallet.name;
29
30
@action
32
- Future updateWalletList() async {
31
+ Future<void> updateWalletList() async {
32
wallets = await _walletListService.getAll();
33
}
34
35
@action
37
- Future loadWallet(WalletDescription wallet) async {
36
+ Future<void> loadWallet(WalletDescription wallet) async {
37
await _walletListService.openWallet(wallet.name);
38
}
39
40
@action
42
- Future remove(WalletDescription wallet) async {
41
+ Future<void> remove(WalletDescription wallet) async {
42
await _walletListService.remove(wallet);
43
await updateWalletList();
44
}
lib/src/stores/wallet_restoration/wallet_restoration_state.dart
+3
-2
@@ -9,6 +9,7 @@ class WalletIsRestoring extends WalletRestorationState {}
9
class WalletRestoredSuccessfully extends WalletRestorationState {}
10
11
class WalletRestorationFailure extends WalletRestorationState {
12
- String error;
12
WalletRestorationFailure({@required this.error});
14
-}
\ No newline at end of file
13
+
14
+ String error;
15
+}
lib/src/stores/wallet_restoration/wallet_restoration_store.dart
+16
-14
@@ -14,6 +14,14 @@ class WalletRestorationStore = WalleRestorationStoreBase
14
with _$WalletRestorationStore;
15
16
abstract class WalleRestorationStoreBase with Store {
17
+ WalleRestorationStoreBase(
18
+ {this.seed,
19
+ @required this.authStore,
20
+ @required this.walletListService,
21
+ @required this.sharedPreferences}) {
22
+ state = WalletRestorationStateInitial();
23
+ }
24
+
25
final AuthenticationStore authStore;
26
final WalletListService walletListService;
27
final SharedPreferences sharedPreferences;
@@ -30,14 +38,6 @@ abstract class WalleRestorationStoreBase with Store {
38
@observable
39
List<MnemoticItem> seed;
40
33
- WalleRestorationStoreBase(
34
- {this.seed,
35
- @required this.authStore,
36
- @required this.walletListService,
37
- @required this.sharedPreferences}) {
38
- state = WalletRestorationStateInitial();
39
- }
40
-
41
@action
42
Future restoreFromSeed({String name, String seed, int restoreHeight}) async {
43
state = WalletRestorationStateInitial();
@@ -110,17 +110,18 @@ abstract class WalleRestorationStoreBase with Store {
110
}
111
112
void validateWalletName(String value) {
113
- String p = '^[a-zA-Z0-9_]{1,15}\$';
114
- RegExp regExp = new RegExp(p);
113
+ const pattern = '^[a-zA-Z0-9_]{1,15}\$';
114
+ final regExp = RegExp(pattern);
115
isValid = regExp.hasMatch(value);
116
errorMessage = isValid ? null : S.current.error_text_wallet_name;
117
}
118
119
void validateAddress(String value, {CryptoCurrency cryptoCurrency}) {
120
// XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34)
121
- String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
122
- RegExp regExp = new RegExp(p);
121
+ const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$';
122
+ final regExp = RegExp(pattern);
123
isValid = regExp.hasMatch(value);
124
+
125
if (isValid && cryptoCurrency != null) {
126
switch (cryptoCurrency.toString()) {
127
case 'XMR':
@@ -142,12 +143,13 @@ abstract class WalleRestorationStoreBase with Store {
143
isValid = (value.length == 34);
144
}
145
}
146
+
147
errorMessage = isValid ? null : S.current.error_text_address;
148
}
149
150
void validateKeys(String value) {
149
- String p = '^[A-Fa-f0-9]{64}\$';
150
- RegExp regExp = new RegExp(p);
151
+ const pattern = '^[A-Fa-f0-9]{64}\$';
152
+ final regExp = RegExp(pattern);
153
isValid = regExp.hasMatch(value);
154
errorMessage = isValid ? null : S.current.error_text_keys;
155
}
lib/src/stores/wallet_seed/wallet_seed_store.dart
+6
-6
@@ -7,12 +7,6 @@ part 'wallet_seed_store.g.dart';
7
class WalletSeedStore = WalletSeedStoreBase with _$WalletSeedStore;
8
9
abstract class WalletSeedStoreBase with Store {
10
- @observable
11
- String name;
12
-
13
- @observable
14
- String seed;
15
-
10
WalletSeedStoreBase({@required WalletService walletService}) {
11
seed = '';
12
@@ -21,4 +15,10 @@ abstract class WalletSeedStoreBase with Store {
15
walletService.getName().then((name) => this.name = name);
16
}
17
}
18
+
19
+ @observable
20
+ String name;
21
+
22
+ @observable
23
+ String seed;
24
}
lib/src/widgets/address_text_field.dart
+17
-18
@@ -9,17 +9,6 @@ import 'package:cake_wallet/src/domain/common/qr_scanner.dart';
9
enum AddressTextFieldOption { qrCode, addressBook, subaddressList }
10
11
class AddressTextField extends StatelessWidget {
12
- static const prefixIconWidth = 34.0;
13
- static const prefixIconHeight = 34.0;
14
- static const spaceBetweenPrefixIcons = 10.0;
15
-
16
- final TextEditingController controller;
17
- final bool isActive;
18
- final String placeholder;
19
- final Function(Uri) onURIScanned;
20
- final List<AddressTextFieldOption> options;
21
- final FormFieldValidator<String> validator;
22
-
12
AddressTextField(
13
{@required this.controller,
14
this.isActive = true,
@@ -31,6 +20,17 @@ class AddressTextField extends StatelessWidget {
20
this.onURIScanned,
21
this.validator});
22
23
+ static const prefixIconWidth = 34.0;
24
+ static const prefixIconHeight = 34.0;
25
+ static const spaceBetweenPrefixIcons = 10.0;
26
+
27
+ final TextEditingController controller;
28
+ final bool isActive;
29
+ final String placeholder;
30
+ final Function(Uri) onURIScanned;
31
+ final List<AddressTextFieldOption> options;
32
+ final FormFieldValidator<String> validator;
33
+
34
@override
35
Widget build(BuildContext context) {
36
return TextFormField(
@@ -105,8 +105,7 @@ class AddressTextField extends StatelessWidget {
105
hintStyle: TextStyle(color: Theme.of(context).hintColor),
106
hintText: placeholder ?? S.current.widgets_address,
107
focusedBorder: UnderlineInputBorder(
108
- borderSide:
109
- BorderSide(color: Palette.cakeGreen, width: 2.0)),
108
+ borderSide: BorderSide(color: Palette.cakeGreen, width: 2.0)),
109
enabledBorder: UnderlineInputBorder(
110
borderSide:
111
BorderSide(color: Theme.of(context).focusColor, width: 1.0)),
@@ -115,10 +114,10 @@ class AddressTextField extends StatelessWidget {
114
);
115
}
116
118
- Future _presentQRScanner(BuildContext context) async {
117
+ Future<void> _presentQRScanner(BuildContext context) async {
118
try {
120
- String code = await presentQRScanner();
121
- var uri = Uri.parse(code);
119
+ final code = await presentQRScanner();
120
+ final uri = Uri.parse(code);
121
var address = '';
122
123
if (uri == null) {
@@ -137,7 +136,7 @@ class AddressTextField extends StatelessWidget {
136
}
137
}
138
140
- Future _presetAddressBookPicker(BuildContext context) async {
139
+ Future<void> _presetAddressBookPicker(BuildContext context) async {
140
final contact = await Navigator.of(context, rootNavigator: true)
141
.pushNamed(Routes.pickerAddressBook);
142
@@ -146,7 +145,7 @@ class AddressTextField extends StatelessWidget {
145
}
146
}
147
149
- Future _presetSubaddressListPicker(BuildContext context) async {
148
+ Future<void> _presetSubaddressListPicker(BuildContext context) async {
149
final subaddress = await Navigator.of(context, rootNavigator: true)
150
.pushNamed(Routes.subaddressList);
151
lib/src/widgets/nav_bar.dart
+26
-26
@@ -5,8 +5,23 @@ import 'package:flutter/material.dart';
5
import 'package:provider/provider.dart';
6
7
class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget {
8
- static const _originalHeight = 44.0; // iOS nav bar height
9
- static const _height = 60.0;
8
+ factory NavBar(
9
+ {BuildContext context,
10
+ Widget leading,
11
+ Widget middle,
12
+ Widget trailing,
13
+ Color backgroundColor}) {
14
+ final _themeChanger = Provider.of<ThemeChanger>(context);
15
+ final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
16
+
17
+ return NavBar._internal(
18
+ leading: leading,
19
+ middle: middle,
20
+ trailing: trailing,
21
+ height: _height,
22
+ backgroundColor:
23
+ _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor);
24
+ }
25
26
factory NavBar.withShadow(
27
{BuildContext context,
@@ -37,23 +52,16 @@ class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget {
52
);
53
}
54
40
- factory NavBar(
41
- {BuildContext context,
42
- Widget leading,
43
- Widget middle,
44
- Widget trailing,
45
- Color backgroundColor}) {
46
- final _themeChanger = Provider.of<ThemeChanger>(context);
47
- final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
55
+ NavBar._internal(
56
+ {this.leading,
57
+ this.middle,
58
+ this.trailing,
59
+ this.backgroundColor,
60
+ this.decoration,
61
+ this.height = _height});
62
49
- return NavBar._internal(
50
- leading: leading,
51
- middle: middle,
52
- trailing: trailing,
53
- height: _height,
54
- backgroundColor:
55
- _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor);
56
- }
63
+ static const _originalHeight = 44.0; // iOS nav bar height
64
+ static const _height = 60.0;
65
66
final Widget leading;
67
final Widget middle;
@@ -62,14 +70,6 @@ class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget {
70
final BoxDecoration decoration;
71
final double height;
72
65
- NavBar._internal(
66
- {this.leading,
67
- this.middle,
68
- this.trailing,
69
- this.backgroundColor,
70
- this.decoration,
71
- this.height = _height});
72
-
73
@override
74
Widget build(BuildContext context) {
75
final pad = height - _originalHeight;
lib/src/widgets/picker.dart
+14
-10
@@ -2,12 +2,6 @@ import 'dart:ui';
2
import 'package:flutter/material.dart';
3
4
class Picker<Item extends Object> extends StatelessWidget {
5
- final int selectedAtIndex;
6
- final List<Item> items;
7
- final String title;
8
- final double pickerHeight;
9
- final Function(Item) onItemSelected;
10
-
5
Picker(
6
{@required this.selectedAtIndex,
7
@required this.items,
@@ -15,9 +9,14 @@ class Picker<Item extends Object> extends StatelessWidget {
9
this.pickerHeight = 300,
10
this.onItemSelected});
11
12
+ final int selectedAtIndex;
13
+ final List<Item> items;
14
+ final String title;
15
+ final double pickerHeight;
16
+ final Function(Item) onItemSelected;
17
+
18
@override
19
Widget build(BuildContext context) {
20
-
20
return GestureDetector(
21
onTap: () => Navigator.of(context).pop(),
22
child: Container(
@@ -57,8 +56,10 @@ class Picker<Item extends Object> extends StatelessWidget {
56
fontWeight: FontWeight.w600,
57
fontFamily: 'Lato',
58
decoration: TextDecoration.none,
60
- color: Theme.of(context).primaryTextTheme.caption.color
61
- ),
59
+ color: Theme.of(context)
60
+ .primaryTextTheme
61
+ .caption
62
+ .color),
63
),
64
),
65
);
@@ -88,7 +89,10 @@ class Picker<Item extends Object> extends StatelessWidget {
89
fontFamily: 'Lato',
90
color: index == selectedAtIndex
91
? Color.fromRGBO(138, 80, 255, 1)
91
- : Theme.of(context).primaryTextTheme.caption.color),
92
+ : Theme.of(context)
93
+ .primaryTextTheme
94
+ .caption
95
+ .color),
96
)),
97
),
98
);
lib/src/widgets/primary_button.dart
+36
-34
@@ -3,20 +3,19 @@ import 'package:flutter/material.dart';
3
import 'package:cake_wallet/palette.dart';
4
5
class PrimaryButton extends StatelessWidget {
6
- final VoidCallback onPressed;
7
- final Color color;
8
- final Color borderColor;
9
- final String text;
10
-
6
const PrimaryButton(
7
{@required this.onPressed,
8
@required this.text,
9
@required this.color,
10
@required this.borderColor});
11
12
+ final VoidCallback onPressed;
13
+ final Color color;
14
+ final Color borderColor;
15
+ final String text;
16
+
17
@override
18
Widget build(BuildContext context) {
19
-
19
return ButtonTheme(
20
minWidth: double.infinity,
21
height: 56.0,
@@ -35,13 +34,6 @@ class PrimaryButton extends StatelessWidget {
34
}
35
36
class LoadingPrimaryButton extends StatelessWidget {
38
- final VoidCallback onPressed;
39
- final Color color;
40
- final Color borderColor;
41
- final bool isLoading;
42
- final bool isDisabled;
43
- final String text;
44
-
37
const LoadingPrimaryButton(
38
{@required this.onPressed,
39
@required this.text,
@@ -50,9 +42,15 @@ class LoadingPrimaryButton extends StatelessWidget {
42
this.isDisabled = false,
43
this.isLoading = false});
44
45
+ final VoidCallback onPressed;
46
+ final Color color;
47
+ final Color borderColor;
48
+ final bool isLoading;
49
+ final bool isDisabled;
50
+ final String text;
51
+
52
@override
53
Widget build(BuildContext context) {
55
-
54
return ButtonTheme(
55
minWidth: double.infinity,
56
height: 56.0,
@@ -73,14 +71,6 @@ class LoadingPrimaryButton extends StatelessWidget {
71
}
72
73
class PrimaryIconButton extends StatelessWidget {
76
- final VoidCallback onPressed;
77
- final IconData iconData;
78
- final Color color;
79
- final Color borderColor;
80
- final Color iconColor;
81
- final Color iconBackgroundColor;
82
- final String text;
83
-
74
const PrimaryIconButton({
75
@required this.onPressed,
76
@required this.iconData,
@@ -91,9 +81,16 @@ class PrimaryIconButton extends StatelessWidget {
81
@required this.iconBackgroundColor,
82
});
83
84
+ final VoidCallback onPressed;
85
+ final IconData iconData;
86
+ final Color color;
87
+ final Color borderColor;
88
+ final Color iconColor;
89
+ final Color iconBackgroundColor;
90
+ final String text;
91
+
92
@override
93
Widget build(BuildContext context) {
96
-
94
return ButtonTheme(
95
minWidth: double.infinity,
96
height: 56.0,
@@ -123,7 +120,8 @@ class PrimaryIconButton extends StatelessWidget {
120
child: Text(text,
121
style: TextStyle(
122
fontSize: 16.0,
126
- color: Theme.of(context).primaryTextTheme.button.color)),
123
+ color:
124
+ Theme.of(context).primaryTextTheme.button.color)),
125
),
126
)
127
],
@@ -133,13 +131,6 @@ class PrimaryIconButton extends StatelessWidget {
131
}
132
133
class PrimaryImageButton extends StatelessWidget {
136
- final VoidCallback onPressed;
137
- final Image image;
138
- final Color color;
139
- final Color borderColor;
140
- final Color iconColor;
141
- final String text;
142
-
134
const PrimaryImageButton(
135
{@required this.onPressed,
136
@required this.image,
@@ -148,6 +139,13 @@ class PrimaryImageButton extends StatelessWidget {
139
this.borderColor = Palette.deepPink,
140
this.iconColor = Colors.black});
141
142
+ final VoidCallback onPressed;
143
+ final Image image;
144
+ final Color color;
145
+ final Color borderColor;
146
+ final Color iconColor;
147
+ final String text;
148
+
149
@override
150
Widget build(BuildContext context) {
151
return ButtonTheme(
@@ -175,9 +173,13 @@ class PrimaryImageButton extends StatelessWidget {
173
Container(
174
height: 56.0,
175
child: Center(
178
- child: Text(text, style: TextStyle(fontSize: 18.0,
179
- color: Theme.of(context).primaryTextTheme.button.color
180
- )),
176
+ child: Text(text,
177
+ style: TextStyle(
178
+ fontSize: 18.0,
179
+ color: Theme.of(context)
180
+ .primaryTextTheme
181
+ .button
182
+ .color)),
183
),
184
)
185
]))
lib/src/widgets/scollable_with_bottom_section.dart
+5
-5
@@ -2,17 +2,17 @@ import 'package:flutter/cupertino.dart';
2
import 'package:flutter/material.dart';
3
4
class ScrollableWithBottomSection extends StatefulWidget {
5
- final Widget content;
6
- final Widget bottomSection;
7
- final EdgeInsets contentPadding;
8
- final EdgeInsets bottomSectionPadding;
9
-
5
ScrollableWithBottomSection(
6
{this.content,
7
this.bottomSection,
8
this.contentPadding,
9
this.bottomSectionPadding});
10
11
+ final Widget content;
12
+ final Widget bottomSection;
13
+ final EdgeInsets contentPadding;
14
+ final EdgeInsets bottomSectionPadding;
15
+
16
@override
17
ScrollableWithBottomSectionState createState() =>
18
ScrollableWithBottomSectionState();
lib/src/widgets/seed_widget.dart
+4
-4
@@ -7,10 +7,11 @@ import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
7
import 'package:cake_wallet/generated/i18n.dart';
8
9
class SeedWidget extends StatefulWidget {
10
- final Function(List<MnemoticItem>) onMnemoticChange;
11
-
10
SeedWidget({Key key, this.onMnemoticChange}) : super(key: key);
11
12
+ final Function(List<MnemoticItem>) onMnemoticChange;
13
+
14
+ @override
15
SeedWidgetState createState() => SeedWidgetState();
16
}
17
@@ -188,8 +189,7 @@ class SeedWidgetState extends State<SeedWidget> {
189
hintStyle: TextStyle(color: Theme.of(context).hintColor),
190
hintText: S.of(context).widgets_seed,
191
focusedBorder: UnderlineInputBorder(
191
- borderSide: BorderSide(
192
- color: Palette.cakeGreen, width: 2.0)),
192
+ borderSide: BorderSide(color: Palette.cakeGreen, width: 2.0)),
193
enabledBorder: UnderlineInputBorder(
194
borderSide: BorderSide(
195
color:
lib/src/widgets/standart_switch.dart
+9
-22
@@ -1,41 +1,31 @@
1
import 'package:flutter/material.dart';
2
3
class StandartSwitch extends StatefulWidget {
4
+ const StandartSwitch({@required this.value, @required this.onTaped});
5
6
final bool value;
7
final VoidCallback onTaped;
8
8
- const StandartSwitch({
9
- @required this.value,
10
- @required this.onTaped});
11
-
9
@override
13
- createState() => StandartSwitchState();
14
-
10
+ StandartSwitchState createState() => StandartSwitchState();
11
}
12
13
class StandartSwitchState extends State<StandartSwitch> {
18
-
14
@override
15
Widget build(BuildContext context) {
21
-
16
return GestureDetector(
17
onTap: widget.onTaped,
18
child: AnimatedContainer(
19
padding: EdgeInsets.only(left: 4.0, right: 4.0),
26
- alignment: widget.value
27
- ? Alignment.centerRight
28
- : Alignment.centerLeft,
20
+ alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft,
21
duration: Duration(milliseconds: 250),
22
width: 55.0,
23
height: 33.0,
24
decoration: BoxDecoration(
25
color: Theme.of(context).toggleButtonsTheme.color,
26
border: Border.all(
35
- color: Theme.of(context).toggleButtonsTheme.borderColor
36
- ),
37
- borderRadius:
38
- BorderRadius.all(Radius.circular(10.0))),
27
+ color: Theme.of(context).toggleButtonsTheme.borderColor),
28
+ borderRadius: BorderRadius.all(Radius.circular(10.0))),
29
child: Container(
30
width: 25.0,
31
height: 25.0,
@@ -43,11 +33,9 @@ class StandartSwitchState extends State<StandartSwitch> {
33
color: widget.value
34
? Theme.of(context).toggleButtonsTheme.selectedColor
35
: Theme.of(context).toggleButtonsTheme.disabledColor,
46
- borderRadius:
47
- BorderRadius.all(Radius.circular(8.0))),
48
- child: Icon(widget.value
49
- ? Icons.check
50
- : Icons.close,
36
+ borderRadius: BorderRadius.all(Radius.circular(8.0))),
37
+ child: Icon(
38
+ widget.value ? Icons.check : Icons.close,
39
color: Colors.white,
40
size: 16.0,
41
),
@@ -55,5 +43,4 @@ class StandartSwitchState extends State<StandartSwitch> {
43
),
44
);
45
}
58
-
59
-}
\ No newline at end of file
46
+}
lib/theme_changer.dart
+4
-5
@@ -1,17 +1,16 @@
1
import 'package:flutter/material.dart';
2
3
class ThemeChanger with ChangeNotifier {
4
+
5
+ ThemeChanger(this._themeData);
6
7
ThemeData _themeData;
8
7
- ThemeChanger(this._themeData);
8
-
9
- getTheme() => _themeData;
9
+ ThemeData getTheme() => _themeData;
10
11
- setTheme(ThemeData theme){
11
+ void setTheme(ThemeData theme){
12
_themeData = theme;
13
14
notifyListeners();
15
}
16
-
16
}
\ No newline at end of file
pubspec.lock
+1
-1
@@ -498,7 +498,7 @@ packages:
498
source: hosted
499
version: "1.5.1"
500
pedantic:
501
- dependency: transitive
501
+ dependency: "direct dev"
502
description:
503
name: pedantic
504
url: "https://pub.dartlang.org"
pubspec.yaml
+1
@@ -59,6 +59,7 @@ dev_dependencies:
59
mobx_codegen: 0.3.3+1
60
hive_generator: ^0.6.0
61
flutter_launcher_icons: ^0.7.4
62
+ pedantic: ^1.8.0
63
64
flutter_icons:
65
image_path: "assets/images/app_logo.png"
tool/secrets.dart
+2
-2
@@ -12,9 +12,9 @@ Future<void> main() async {
12
: secretsTestPath;
13
14
final inoutContent = File(inputPath).readAsStringSync();
15
- final config = json.decode(inoutContent);
15
+ final config = json.decode(inoutContent) as Map<String, String>;
16
final output =
17
'const salt = \'${config["salt"]}\';\nconst key = \'${config["key"]}\';\nconst walletSalt = \'${config["walletSalt"]}\';\nconst shortKey = \'${config["shortKey"]}\';\nconst change_now_api_key = \'${config["change_now_api_key"]}\';';
18
19
- File(outputPath).writeAsString(output);
19
+ await File(outputPath).writeAsString(output);
20
}