This commit is contained in:
M 2020-10-29 12:49:07 +02:00
parent 44e55f0bc4
commit b8e435ea8e
14 changed files with 250 additions and 119 deletions

View file

@ -87,7 +87,7 @@ extern "C"
void updated()
{
m_need_to_refresh = true;
m_new_transaction = true;
}
void refreshed()
@ -472,7 +472,9 @@ extern "C"
return false;
}
m_listener->m_new_transaction = true;
if (m_listener != nullptr) {
m_listener->m_new_transaction = true;
}
pendingTransaction = PendingTransactionRaw(transaction);
return true;
@ -485,7 +487,7 @@ extern "C"
if (!committed)
{
error = Utf8Box(strdup(transaction->transaction->errorString().c_str()));
} else {
} else if (m_listener != nullptr) {
m_listener->m_new_transaction = true;
}
@ -508,9 +510,13 @@ extern "C"
}
uint64_t height = m_listener->height();
uint64_t node_height = get_node_height_or_update(height);
// uint64_t node_height = get_node_height_or_update(height);
//
// if (height <= 1 || node_height <= 0) {
// return 0;
// }
if (height <= 1 || node_height <= 0) {
if (height <= 1) {
return 0;
}
@ -529,10 +535,14 @@ extern "C"
}
bool should_refresh = m_listener->isNeedToRefresh();
uint64_t node_height = get_node_height_or_update(m_last_known_wallet_height);
// uint64_t node_height = get_node_height_or_update(m_last_known_wallet_height);
//
// if (should_refresh || (node_height - m_last_known_wallet_height < MONERO_BLOCK_SIZE))
// {
// m_listener->resetNeedToRefresh();
// }
if (should_refresh || (node_height - m_last_known_wallet_height < MONERO_BLOCK_SIZE))
{
if (should_refresh) {
m_listener->resetNeedToRefresh();
}
@ -561,7 +571,7 @@ extern "C"
if (m_listener != nullptr)
{
// free(m_listener);
free(m_listener);
}
m_listener = new MoneroWalletListener();

View file

@ -26,7 +26,18 @@ final accountSetLabelNative = moneroApi
.lookup<NativeFunction<account_set_label>>('account_set_label_row')
.asFunction<AccountSetLabel>();
void refreshAccounts() => accountRefreshNative();
bool isUpdating = false;
void refreshAccounts() {
try {
isUpdating = true;
accountRefreshNative();
isUpdating = false;
} catch (e) {
isUpdating = false;
rethrow;
}
}
List<AccountRow> getAllAccount() {
final size = accountSizeNative();
@ -63,4 +74,4 @@ Future<void> addAccount({String label}) async => compute(_addAccount, label);
Future<void> setLabelForAccount({int accountIndex, String label}) async =>
compute(
_setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
_setLabelForAccount, {'accountIndex': accountIndex, 'label': label});

View file

@ -26,8 +26,18 @@ final subaddrressSetLabelNative = moneroApi
.lookup<NativeFunction<subaddress_set_label>>('subaddress_set_label')
.asFunction<SubaddressSetLabel>();
void refreshSubaddresses({int accountIndex}) =>
bool isUpdating = false;
void refreshSubaddresses({@required int accountIndex}) {
try {
isUpdating = true;
subaddressRefreshNative(accountIndex);
isUpdating = false;
} catch (e) {
isUpdating = false;
rethrow;
}
}
List<SubaddressRow> getAllSubaddresses() {
final size = subaddressSizeNative();
@ -48,7 +58,7 @@ void addSubaddressSync({int accountIndex, String label}) {
void setLabelForSubaddressSync(
{int accountIndex, int addressIndex, String label}) {
final labelPointer = Utf8.toUtf8(label);
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
free(labelPointer);
}
@ -70,7 +80,8 @@ void _setLabelForSubaddress(Map<String, dynamic> args) {
}
Future addSubaddress({int accountIndex, String label}) async =>
compute<Map<String, Object>, void>(_addSubaddress, {'accountIndex': accountIndex, 'label': label});
compute<Map<String, Object>, void>(
_addSubaddress, {'accountIndex': accountIndex, 'label': label});
Future setLabelForSubaddress(
{int accountIndex, int addressIndex, String label}) =>

View file

@ -114,6 +114,8 @@ final rescanBlockchainAsyncNative = moneroApi
.lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
.asFunction<RescanBlockchainAsync>();
bool isStoring = false;
int getSyncingHeight() => getSyncingHeightNative();
bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
@ -209,8 +211,8 @@ String getSecretSpendKey() =>
String getPublicSpendKey() =>
convertUTF8ToString(pointer: getPublicSpendKeyNative());
class SyncListner {
SyncListner({this.onNewBlock, this.onNeedToRefresh, this.onNewTransaction});
class SyncListener {
SyncListener({this.onNewBlock, this.onNeedToRefresh, this.onNewTransaction});
void Function(int, int, double) onNewBlock;
void Function() onNeedToRefresh;
@ -234,7 +236,7 @@ class SyncListner {
_lastKnownBlockHeight = 0;
_initialSyncHeight = 0;
_updateSyncInfoTimer ??=
Timer.periodic(Duration(milliseconds: 200), (_) async {
Timer.periodic(Duration(milliseconds: 1200), (_) async {
final syncHeight = getSyncingHeight();
final needToRefresh = isNeededToRefresh();
final newTransactionExist = isNewTransactionExist();
@ -251,7 +253,7 @@ class SyncListner {
final ptc = diff <= 0 ? 0.0 : diff / line;
final left = bchHeight - syncHeight;
// 1. Actual new height; 2. Blocks left to finish; 3. Progress in percents;
onNewBlock(syncHeight, left, ptc);
onNewBlock?.call(syncHeight, left, ptc);
}
if (newTransactionExist) {
@ -267,9 +269,9 @@ class SyncListner {
void stop() => _updateSyncInfoTimer?.cancel();
}
SyncListner setListeners(void Function(int, int, double) onNewBlock,
SyncListener setListeners(void Function(int, int, double) onNewBlock,
void Function() onNeedToRefresh, void Function() onNewTransaction) {
final listener = SyncListner(
final listener = SyncListener(
onNewBlock: onNewBlock,
onNeedToRefresh: onNeedToRefresh,
onNewTransaction: onNewTransaction);
@ -281,7 +283,20 @@ SyncListner setListeners(void Function(int, int, double) onNewBlock,
void onStartup() => onStartupNative();
void _storeSync(Object _) => storeSync();
void _storeSync(Object _) {
if (isStoring) {
return;
}
try {
isStoring = true;
storeSync();
isStoring = false;
} catch (e) {
isStoring = false;
rethrow;
}
}
bool _setupNodeSync(Map args) {
final address = args['address'] as String;

View file

@ -2,25 +2,25 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
</dict>
</plist>

View file

@ -354,7 +354,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 11;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -362,6 +362,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -493,7 +494,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 11;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -501,6 +502,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -526,7 +528,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 11;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -534,6 +536,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View file

@ -67,8 +67,22 @@ final dates = {
"2019-5": 1824671,
"2019-6": 1847005,
"2019-7": 1868590,
"2019-8": 1888590,
"2019-9": 1898590,
"2019-8": 1890552,
"2019-9": 1912212,
"2019-10": 1932200,
"2019-11": 1957040,
"2019-12": 1978090,
"2020-1": 2001290,
"2020-2": 2022688,
"2020-3": 2043987,
"2020-4": 2066536,
"2020-5": 2090797,
"2020-6": 2111633,
"2020-7": 2131433,
"2020-8": 2153983,
"2020-9": 2176466,
"2020-10": 2198453,
"2020-11": 2221803
};
int getHeigthByDate({DateTime date}) {

View file

@ -19,7 +19,6 @@ import 'package:cake_wallet/entities/wallet_info.dart';
import 'package:cake_wallet/entities/node.dart';
import 'package:cake_wallet/entities/transaction_priority.dart';
part 'monero_wallet.g.dart';
const moneroBlockSize = 1000;
@ -80,7 +79,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
final MoneroAccountList accountList;
String _filename;
SyncListner _listener;
SyncListener _listener;
ReactionDisposer _onAccountChangeReaction;
int _cachedRefreshHeight;
@ -96,6 +95,15 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
address = subaddress.address;
_setListeners();
await transactionHistory.update();
if (walletInfo.isRecovery) {
monero_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery);
if (monero_wallet.getCurrentHeight() <= 1) {
monero_wallet.setRefreshFromBlockHeight(
height: walletInfo.restoreHeight);
}
}
}
void close() {
@ -103,6 +111,24 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
_onAccountChangeReaction?.reaction?.dispose();
}
Future<bool> validate() async {
await accountList.update();
final accountListLength = accountList.accounts?.length ?? 0;
if (accountListLength <= 0) {
return false;
}
subaddressList.update(accountIndex: accountList.accounts.first.id);
final subaddressListLength = subaddressList.subaddresses?.length ?? 0;
if (subaddressListLength <= 0) {
return false;
}
return true;
}
@override
Future<void> connectToNode({@required Node node}) async {
try {
@ -275,8 +301,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
return;
}
syncStatus = SyncedSyncStatus();
if (walletInfo.isRecovery) {
_askForUpdateTransactionHistory();
_askForUpdateBalance();
@ -285,11 +309,19 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
final currentHeight = getCurrentHeight();
final nodeHeight = monero_wallet.getNodeHeightSync();
if (walletInfo.isRecovery &&
(nodeHeight - currentHeight < moneroBlockSize)) {
await setAsRecovered();
if (nodeHeight - currentHeight < moneroBlockSize) {
syncStatus = SyncedSyncStatus();
if (walletInfo.isRecovery) {
await setAsRecovered();
}
}
// if (walletInfo.isRecovery &&
// (nodeHeight - currentHeight < moneroBlockSize)) {
// await setAsRecovered();
// }
if (currentHeight - _cachedRefreshHeight > moneroBlockSize) {
_cachedRefreshHeight = currentHeight;
await save();

View file

@ -25,6 +25,11 @@ class MoneroRestoreWalletFromSeedCredentials extends WalletCredentials {
final String mnemonic;
}
class MoneroWalletLoadingException implements Exception {
@override
String toString() => 'The wallet is damaged.';
}
class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials {
MoneroRestoreWalletFromKeysCredentials(
{String name,
@ -88,11 +93,29 @@ class MoneroWalletService extends WalletService<
Future<MoneroWallet> openWallet(String name, String password) async {
try {
final path = await pathForWallet(name: name, type: WalletType.monero);
await monero_wallet_manager.openWalletAsync({'path': path, 'password': password});
await monero_wallet_manager
.openWalletAsync({'path': path, 'password': password});
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, WalletType.monero), orElse: () => null);
(info) => info.id == WalletBase.idFor(name, WalletType.monero),
orElse: () => null);
final wallet = MoneroWallet(
filename: monero_wallet.getFilename(), walletInfo: walletInfo);
final isValid = await wallet.validate();
if (!isValid) {
if (wallet.seed?.isNotEmpty ?? false) {
// let restore from seed in this case;
final seed = wallet.seed;
final credentials = MoneroRestoreWalletFromSeedCredentials(
name: name, password: password, mnemonic: seed, height: 2000000)
..walletInfo = walletInfo;
await remove(name);
return restoreFromSeed(credentials);
}
throw MoneroWalletLoadingException();
}
await wallet.init();
return wallet;
@ -104,9 +127,15 @@ class MoneroWalletService extends WalletService<
}
@override
Future<void> remove(String wallet) async =>
File(await pathForWalletDir(name: wallet, type: WalletType.bitcoin))
.delete(recursive: true);
Future<void> remove(String wallet) async {
final path = await pathForWalletDir(name: wallet, type: WalletType.monero);
final file = Directory(path);
final isExist = file.existsSync();
if (isExist) {
await file.delete(recursive: true);
}
}
@override
Future<MoneroWallet> restoreFromKeys(

View file

@ -32,42 +32,41 @@ class AnnotatedEditableText extends EditableText {
Color selectionColor,
Color backgroundCursorColor,
TextSelectionControls selectionControls,
TextStyle textStyle = const TextStyle(
color: Colors.black,
backgroundColor: Colors.transparent,
fontWeight: FontWeight.normal,
fontSize: 16),
@required this.words,
}) : textAnnotations = words
.map((word) => TextAnnotation(
text: word,
style: TextStyle(
color: Colors.black,
backgroundColor: Colors.transparent,
fontWeight: FontWeight.normal,
fontSize: 16)))
.toList(),
.map((word) => TextAnnotation(text: word, style: textStyle))
.toList(),
super(
maxLines: null,
key: key,
focusNode: focusNode,
controller: controller,
cursorColor: cursorColor,
style: style,
keyboardType: TextInputType.text,
autocorrect: false,
autofocus: false,
selectionColor: selectionColor,
selectionControls: selectionControls,
backgroundCursorColor: backgroundCursorColor,
onChanged: onChanged,
onSubmitted: onSubmitted,
toolbarOptions: const ToolbarOptions(
copy: true,
cut: true,
paste: true,
selectAll: true,
),
enableSuggestions: false,
enableInteractiveSelection: true,
showSelectionHandles: true,
showCursor: true,
) {
maxLines: null,
key: key,
focusNode: focusNode,
controller: controller,
cursorColor: cursorColor,
style: style,
keyboardType: TextInputType.text,
autocorrect: false,
autofocus: false,
selectionColor: selectionColor,
selectionControls: selectionControls,
backgroundCursorColor: backgroundCursorColor,
onChanged: onChanged,
onSubmitted: onSubmitted,
toolbarOptions: const ToolbarOptions(
copy: true,
cut: true,
paste: true,
selectAll: true,
),
enableSuggestions: false,
enableInteractiveSelection: true,
showSelectionHandles: true,
showCursor: true,
) {
textAnnotations.add(TextAnnotation(
text: ' ', style: TextStyle(backgroundColor: Colors.transparent)));
}
@ -86,7 +85,7 @@ class AnnotatedEditableTextState extends EditableTextState {
List<Annotation> getRanges() {
final source = widget.textAnnotations
.map((item) => range(item.text, textEditingValue.text)
.map((range) => Annotation(style: item.style, range: range)))
.map((range) => Annotation(style: item.style, range: range)))
.expand((e) => e)
.toList();
final result = List<Annotation>();
@ -123,7 +122,7 @@ class AnnotatedEditableTextState extends EditableTextState {
if (result.length > 0 && result.last.range.end < text.length) {
result.add(Annotation(
range: TextRange(start: result.last.range.end, end: text.length),
style: TextStyle( backgroundColor: Colors.transparent)));
style: TextStyle(backgroundColor: Colors.transparent)));
}
return result;
}
@ -132,8 +131,8 @@ class AnnotatedEditableTextState extends EditableTextState {
final result = List<TextRange>();
for (int index = source.indexOf(pattern);
index >= 0;
index = source.indexOf(pattern, index + 1)) {
index >= 0;
index = source.indexOf(pattern, index + 1)) {
final start = index;
final end = start + pattern.length;
result.add(TextRange(start: start, end: end));
@ -152,10 +151,10 @@ class AnnotatedEditableTextState extends EditableTextState {
style: widget.style,
children: ranges
.map((item) => TextSpan(
style: item.style, text: item.range.textInside(text)))
style: item.style, text: item.range.textInside(text)))
.toList());
}
return TextSpan(style: widget.style, text: text);
}
}
}

View file

@ -78,16 +78,22 @@ class SeedWidgetState extends State<SeedWidget> {
Padding(
padding: EdgeInsets.only(right: 40, top: 10),
child: AnnotatedEditableText(
cursorColor: Colors.green,
backgroundCursorColor: Colors.blue,
style: TextStyle(
fontSize: 20,
color: Colors.red,
fontWeight: FontWeight.normal,
backgroundColor: Colors.transparent),
focusNode: focusNode,
controller: controller,
words: words)),
cursorColor: Colors.blue,
backgroundCursorColor: Colors.blue,
style: TextStyle(
fontSize: 16,
color: Colors.red,
fontWeight: FontWeight.normal,
backgroundColor: Colors.transparent),
focusNode: focusNode,
controller: controller,
words: words,
textStyle: TextStyle(
color: Theme.of(context).primaryTextTheme.title.color,
backgroundColor: Colors.transparent,
fontWeight: FontWeight.normal,
fontSize: 16),
)),
Positioned(
top: 0,
right: 0,

View file

@ -34,8 +34,8 @@ abstract class WalletCreationVMBase with Store {
Future<void> create({dynamic options}) async {
try {
name = await generateName();
state = IsExecutingState();
name = await generateName();
final dirPath = await pathForWalletDir(name: name, type: type);
final path = await pathForWallet(name: name, type: type);
final credentials = getCredentials(options);

View file

@ -55,7 +55,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
spendKey: spendKey,
viewKey: viewKey,
address: address,
password: password);
password: password,
language: 'English');
}
return null;

View file

@ -7,14 +7,14 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "11.0.0"
version: "12.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.40.4"
version: "0.40.5"
archive:
dependency: transitive
description:
@ -140,7 +140,7 @@ packages:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.3"
version: "1.10.4"
build_runner_core:
dependency: transitive
description:
@ -575,14 +575,14 @@ packages:
name: mobx
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1+3"
version: "1.2.1+4"
mobx_codegen:
dependency: "direct dev"
description:
name: mobx_codegen
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1+1"
version: "1.1.1+3"
node_interop:
dependency: transitive
description:
@ -729,7 +729,7 @@ packages:
name: protobuf
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.1.0"
provider:
dependency: "direct main"
description:
@ -764,7 +764,7 @@ packages:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
version: "2.1.4+1"
rxdart:
dependency: "direct main"
description:
@ -778,7 +778,7 @@ packages:
name: share
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.5+3"
version: "0.6.5+4"
shared_preferences:
dependency: "direct main"
description:
@ -853,7 +853,7 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.7+1"
version: "0.9.8"
source_span:
dependency: transitive
description:
@ -1023,5 +1023,5 @@ packages:
source: hosted
version: "2.2.1"
sdks:
dart: ">=2.10.0-110 <2.11.0"
dart: ">=2.10.0 <2.11.0"
flutter: ">=1.22.0 <2.0.0"