Merge branch 'staging' into rylee-tmp

This commit is contained in:
ryleedavis 2022-08-29 12:42:34 -06:00
commit 3764494832
21 changed files with 893 additions and 504 deletions

View file

@ -1,5 +1,6 @@
#should deny
name: Test
on: [push, pull_request]
on: [pull_request]
jobs:
test:
runs-on: ubuntu-20.04
@ -13,6 +14,10 @@ jobs:
uses: subosito/flutter-action@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Build Lelantus
run: |
cd crypto_plugins/flutter_liblelantus/scripts/linux/
./build_all.sh
- name: Get dependencies
run: flutter pub get
- name: Create temp files
@ -58,7 +63,13 @@ jobs:
# - name: Analyze
# run: flutter analyze
- name: Test
run: flutter test
run: flutter test --coverage
- name: Upload to code coverage
uses: codecov/codecov-action@v1.2.2
if: success() || failure()
with:
token: ${{secrets.CODECOV_TOKEN}}
file: coverage/lcov.info
- name: Delete temp files
run: |
Remove-Item -Path $env:CHANGE_NOW;

View file

@ -1,3 +1,5 @@
[![codecov](https://codecov.io/gh/cypherstack/stack_wallet/branch/main/graph/badge.svg?token=PM1N56UTEW)](https://codecov.io/gh/cypherstack/stack_wallet)
# Stack Wallet
put details here
@ -8,13 +10,14 @@ put features here
## Build and run
### Prerequisites
- Flutter 3.0.5
- Flutter SDK Requirement (>=2.12.0, up until <3.0.0)
- Android/iOS dev setup (Android Studio, xCode and subsequent dependencies)
After that download the project and init the submodules
```
git clone https://github.com/cypherstack/Campfire.git
cd Campfire
git clone https://github.com/cypherstack/stack_wallet.git
cd stack_wallet
git submodule update --init --recursive
```

View file

@ -87,7 +87,7 @@ linter:
no_leading_underscores_for_local_identifiers: false
no_leading_underscores_for_library_prefixes: false
avoid_print: true
unawaited_futures: false
unawaited_futures: true
avoid_double_and_int_checks: false
constant_identifier_names: false
# avoid_print: false # Uncomment to disable the `avoid_print` rule

View file

@ -53,6 +53,15 @@ android {
ndk {
abiFilters "x86_64","armeabi-v7a", "arm64-v8a"
}
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared", '-DBUILD_TESTING=OFF', "-DANDROID_TOOLCHAIN=clang -v"
cppFlags "-frtti -fexceptions -v -DANDROID -std=c++17"
// cppFlags "-std=c++11"
version "3.10.2"
}
}
}
signingConfigs {

@ -1 +1 @@
Subproject commit 78533fa427ffc582b83cb67a766c8d38fac2abd8
Subproject commit 6242046217abf47b61d9397ae447632b06f853fa

@ -1 +1 @@
Subproject commit 771175e87c629ca1d8db7a4417191bd15012d52f
Subproject commit cd6f9cf62afcb6c1e55b16a76374a8577d85352f

View file

@ -449,7 +449,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 42;
DEVELOPMENT_TEAM = 4DQKUWSG6C;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -503,7 +503,7 @@
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
);
MARKETING_VERSION = 1.4.30;
MARKETING_VERSION = 1.4.34;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -633,7 +633,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 42;
DEVELOPMENT_TEAM = 4DQKUWSG6C;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -687,7 +687,7 @@
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
);
MARKETING_VERSION = 1.4.30;
MARKETING_VERSION = 1.4.34;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -709,7 +709,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 42;
DEVELOPMENT_TEAM = 4DQKUWSG6C;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -763,7 +763,7 @@
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
);
MARKETING_VERSION = 1.4.30;
MARKETING_VERSION = 1.4.34;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
PRODUCT_NAME = "$(TARGET_NAME)";

View file

@ -176,7 +176,14 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
late final Completer<void> loadingCompleter;
bool didLoad = false;
Future<void> load() async {
if (didLoad) {
return;
}
didLoad = true;
await DB.instance.init();
_notificationsService = ref.read(notificationsProvider);

View file

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart';
@ -15,15 +13,10 @@ class AddWalletView extends StatelessWidget {
static const routeName = "/addWallet";
final _coins = Coin.values;
@override
Widget build(BuildContext context) {
List<Coin> coins = _coins;
if (Platform.isIOS) {
coins = _coins;
}
debugPrint("BUILD: $runtimeType");
List<Coin> coins = [...Coin.values];
coins.remove(Coin.firoTestNet);
return Scaffold(
appBar: AppBar(
leading: AppBarBackButton(

View file

@ -1,7 +1,7 @@
import 'dart:async';
import 'dart:collection';
import 'dart:math';
import 'dart:io';
import 'dart:math';
import 'package:bip39/bip39.dart' as bip39;
import 'package:bip39/src/wordlists/english.dart' as bip39wordlist;
@ -26,6 +26,7 @@ import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/custom_text_selection_controls.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
@ -70,25 +71,61 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
final ScrollController controller = ScrollController();
final List<TextEditingController> _controllers = [];
// late final TextEditingController _heightController;
final List<FormInputStatus> _inputStatuses = [];
// late final FocusNode _heightFocusNode;
late final BarcodeScannerInterface scanner;
late final TextSelectionControls textSelectionControls;
Future<void> onControlsPaste(TextSelectionDelegate delegate) async {
final data = await widget.clipboard.getData(Clipboard.kTextPlain);
if (data?.text == null) {
return;
}
final text = data!.text!.trim();
if (text.isEmpty || _controllers.isEmpty) {
delegate.pasteText(SelectionChangedCause.toolbar);
return;
}
final words = text.split(" ");
if (words.isEmpty) {
delegate.pasteText(SelectionChangedCause.toolbar);
return;
}
if (words.length == 1) {
_controllers.first.text = words.first;
if (_isValidMnemonicWord(words.first.toLowerCase())) {
setState(() {
_inputStatuses.first = FormInputStatus.valid;
});
} else {
setState(() {
_inputStatuses.first = FormInputStatus.invalid;
});
}
return;
}
_clearAndPopulateMnemonic(words);
}
@override
void initState() {
_seedWordCount = widget.seedWordsLength;
// _heightFocusNode = FocusNode();
textSelectionControls = Platform.isIOS
? CustomCupertinoTextSelectionControls(onPaste: onControlsPaste)
: CustomMaterialTextSelectionControls(onPaste: onControlsPaste);
scanner = widget.barcodeScanner;
for (int i = 0; i < _seedWordCount; i++) {
_controllers.add(TextEditingController());
_inputStatuses.add(FormInputStatus.empty);
}
// _heightController = TextEditingController();
super.initState();
}
@ -97,8 +134,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
for (var element in _controllers) {
element.dispose();
}
// _heightController.dispose();
// _heightFocusNode.dispose();
super.dispose();
}
@ -404,6 +440,9 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
_inputStatuses[i] = FormInputStatus.empty;
});
}
controller.animateTo(controller.position.maxScrollExtent,
duration: const Duration(milliseconds: 300), curve: Curves.decelerate);
}
@override
@ -442,18 +481,8 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
),
onPressed: () async {
try {
// ref
// .read(shouldShowLockscreenOnResumeStateProvider.state)
// .state = false;
final qrResult = await scanner.scan();
// Future<void>.delayed(
// const Duration(seconds: 2),
// () => ref
// .read(shouldShowLockscreenOnResumeStateProvider.state)
// .state = true,
// );
final results =
AddressUtils.decodeQRSeedData(qrResult.rawContent);
@ -474,9 +503,6 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
}
}
} on PlatformException catch (e) {
// ref
// .read(shouldShowLockscreenOnResumeStateProvider.state)
// .state = true;
// likely failed to get camera permissions
Logging.instance.log("Restore wallet qr scan failed: $e",
level: LogLevel.Warning);
@ -512,9 +538,6 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
final content = data.text!.trim();
final list = content.split(" ");
_clearAndPopulateMnemonic(list);
controller.animateTo(controller.position.maxScrollExtent,
duration: const Duration(milliseconds: 300),
curve: Curves.decelerate);
}
},
),
@ -572,6 +595,8 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
_inputStatuses[i - 1], "$i"),
autovalidateMode:
AutovalidateMode.onUserInteraction,
selectionControls:
i == 1 ? textSelectionControls : null,
onChanged: (value) {
if (value.isEmpty) {
setState(() {

View file

@ -48,7 +48,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
ref.refresh(addressBookFilterProvider);
if (widget.coin == null) {
final coins = Coin.values.where((e) => !(e == Coin.epicCash)).toList();
List<Coin> coins =
Coin.values.where((e) => !(e == Coin.epicCash)).toList();
coins.remove(Coin.firoTestNet);
bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;

View file

@ -23,7 +23,8 @@ class _AddressBookFilterViewState extends ConsumerState<AddressBookFilterView> {
@override
void initState() {
final coins = Coin.values;
List<Coin> coins = [...Coin.values];
coins.remove(Coin.firoTestNet);
bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;

View file

@ -14,6 +14,8 @@ class CoinSelectSheet extends StatelessWidget {
@override
Widget build(BuildContext context) {
final maxHeight = MediaQuery.of(context).size.height * 0.60;
var coins_ = [...Coin.values];
coins_.remove(Coin.firoTestNet);
return Container(
decoration: const BoxDecoration(
color: CFColors.white,
@ -68,10 +70,10 @@ class CoinSelectSheet extends StatelessWidget {
return ListView.builder(
shrinkWrap: true,
itemCount: showTestNet
? Coin.values.length
: Coin.values.length - kTestNetCoinCount,
? coins_.length
: coins_.length - kTestNetCoinCount,
itemBuilder: (builderContext, index) {
final coin = Coin.values[index];
final coin = coins_[index];
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: RawMaterialButton(

View file

@ -23,11 +23,12 @@ class ManageNodesView extends ConsumerStatefulWidget {
}
class _ManageNodesViewState extends ConsumerState<ManageNodesView> {
List<Coin> _coins = Coin.values;
List<Coin> _coins = [...Coin.values];
@override
void initState() {
_coins = _coins.toList();
_coins.remove(Coin.firoTestNet);
super.initState();
}

View file

@ -726,7 +726,7 @@ Future<String> _getMintScriptWrapper(
}
Future<void> _setTestnetWrapper(bool isTestnet) async {
setTestnet(isTestnet);
// setTestnet(isTestnet);
}
/// Handles a single instance of a firo wallet
@ -2893,6 +2893,7 @@ class FiroWallet extends CoinServiceAPI {
}
if (Platform.environment["FLUTTER_TEST"] == "true" || integrationTestFlag) {
perBatch = 10;
numberOfThreads = 4;
}
final receiveDerivationsString =

View file

@ -5,6 +5,7 @@ import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
@ -24,6 +25,7 @@ import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/view_model/send/output.dart' as monero_output;
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart';
import 'package:mutex/mutex.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:stackwallet/hive/db.dart';
@ -121,10 +123,10 @@ class MoneroWallet extends CoinServiceAPI {
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
// TODO: is this sync call needed? Do we need to notify ui here?
walletBase?.startSync();
await walletBase?.startSync();
if (shouldRefresh) {
refresh();
await refresh();
}
}
@ -142,13 +144,37 @@ class MoneroWallet extends CoinServiceAPI {
Future<List<String>> get mnemonic => _getMnemonicList();
Future<int> get currentNodeHeight async {
int currentHeight = await getNodeHeight();
try {
if (walletBase!.syncStatus! is SyncedSyncStatus &&
walletBase!.syncStatus!.progress() == 1.0) {
return await walletBase!.getNodeHeight();
}
} catch (e, s) {}
int _height = -1;
try {
_height = (walletBase!.syncStatus as SyncingSyncStatus).height;
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Warning);
}
int blocksRemaining = -1;
try {
blocksRemaining =
(walletBase!.syncStatus as SyncingSyncStatus).blocksLeft;
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Warning);
}
int currentHeight = _height + blocksRemaining;
if (_height == -1 || blocksRemaining == -1) {
currentHeight = int64MaxValue;
}
final cachedHeight = DB.instance
.get<dynamic>(boxName: walletId, key: "storedNodeHeight") as int? ??
0;
if (currentHeight > cachedHeight) {
DB.instance.put<dynamic>(
if (currentHeight > cachedHeight && currentHeight != int64MaxValue) {
await DB.instance.put<dynamic>(
boxName: walletId, key: "storedNodeHeight", value: currentHeight);
return currentHeight;
} else {
@ -156,29 +182,34 @@ class MoneroWallet extends CoinServiceAPI {
}
}
int get currentSyncingHeight {
Future<int> get currentSyncingHeight async {
//TODO return the tip of the monero blockchain
final syncingHeight = getSyncingHeight();
try {
if (walletBase!.syncStatus! is SyncedSyncStatus &&
walletBase!.syncStatus!.progress() == 1.0) {
Logging.instance
.log("currentSyncingHeight lol", level: LogLevel.Warning);
return getSyncingHeight();
}
} catch (e, s) {}
int syncingHeight = -1;
try {
syncingHeight = (walletBase!.syncStatus as SyncingSyncStatus).height;
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Warning);
}
final cachedHeight =
DB.instance.get<dynamic>(boxName: walletId, key: "storedSyncingHeight")
as int? ??
0;
if (syncingHeight > cachedHeight) {
DB.instance.put<dynamic>(
await DB.instance.put<dynamic>(
boxName: walletId, key: "storedSyncingHeight", value: syncingHeight);
return syncingHeight;
} else {
return cachedHeight;
}
// try {
// final result = await _electrumXClient.getBlockHeadTip();
// return result["height"];
// } catch (e, s) {
// Logging.instance.log("Exception caught in chainHeight: $e\n$s");
// return -1;
// }
}
Future<void> updateStoredChainHeight({required int newHeight}) async {
@ -270,63 +301,78 @@ class MoneroWallet extends CoinServiceAPI {
Timer? syncPercentTimer;
void stopSyncPercentTimer() {
Mutex syncHeightMutex = Mutex();
Future<void> stopSyncPercentTimer() async {
syncPercentTimer?.cancel();
syncPercentTimer = null;
}
void startSyncPercentTimer() {
Future<void> startSyncPercentTimer() async {
if (syncPercentTimer != null) {
return;
}
syncPercentTimer?.cancel();
GlobalEventBus.instance
.fire(RefreshPercentChangedEvent(highestPercentCached, walletId));
syncPercentTimer = Timer.periodic(const Duration(seconds: 3), (_) async {
// int restoreheight = walletBase!.walletInfo.restoreHeight ?? 0;
int _height = currentSyncingHeight;
int _currentHeight = await currentNodeHeight;
final int blocksRemaining = _currentHeight - _height;
GlobalEventBus.instance
.fire(BlocksRemainingEvent(blocksRemaining, walletId));
if (blocksRemaining <= 1 && _currentHeight > 0 && _height > 0) {
stopSyncPercentTimer();
GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.synced,
walletId,
coin,
),
);
syncPercentTimer = Timer.periodic(const Duration(seconds: 30), (_) async {
if (syncHeightMutex.isLocked) {
return;
}
await syncHeightMutex.protect(() async {
// int restoreheight = walletBase!.walletInfo.restoreHeight ?? 0;
int _height = await currentSyncingHeight;
int _currentHeight = await currentNodeHeight;
double progress = 0;
try {
progress = walletBase!.syncStatus!.progress();
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Warning);
}
// for some reason this can be 0 which screws up the percent calculation
// int64MaxValue is NOT the best value to use here
if (_currentHeight < 1) {
_currentHeight = int64MaxValue;
}
final int blocksRemaining = _currentHeight - _height;
if (_height < 1) {
_height = 1;
}
GlobalEventBus.instance
.fire(BlocksRemainingEvent(blocksRemaining, walletId));
double restorePercent = (_height / _currentHeight).clamp(0.0, 1.0);
double highestPercent = highestPercentCached;
if (progress == 1 && _currentHeight > 0 && _height > 0) {
await stopSyncPercentTimer();
GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.synced,
walletId,
coin,
),
);
return;
}
Logging.instance.log(
"currentSyncingHeight: $_height, nodeHeight: $_currentHeight, restorePercent: $restorePercent, highestPercentCached: $highestPercentCached",
level: LogLevel.Info);
// for some reason this can be 0 which screws up the percent calculation
// int64MaxValue is NOT the best value to use here
if (_currentHeight < 1) {
_currentHeight = int64MaxValue;
}
if (restorePercent > 0 && restorePercent <= 1) {
if (restorePercent > highestPercent) {
if (_height < 1) {
_height = 1;
}
double restorePercent = progress;
double highestPercent = highestPercentCached;
Logging.instance.log(
"currentSyncingHeight: $_height, nodeHeight: $_currentHeight, restorePercent: $restorePercent, highestPercentCached: $highestPercentCached",
level: LogLevel.Info);
if (restorePercent > 0 && restorePercent <= 1) {
// if (restorePercent > highestPercent) {
highestPercent = restorePercent;
highestPercentCached = restorePercent;
// }
}
}
GlobalEventBus.instance
.fire(RefreshPercentChangedEvent(highestPercent, walletId));
GlobalEventBus.instance
.fire(RefreshPercentChangedEvent(highestPercent, walletId));
});
});
}
@ -356,7 +402,7 @@ class MoneroWallet extends CoinServiceAPI {
}
try {
startSyncPercentTimer();
await startSyncPercentTimer();
GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.syncing,
@ -365,26 +411,30 @@ class MoneroWallet extends CoinServiceAPI {
),
);
final int _currentSyncingHeight = currentSyncingHeight;
final int _currentSyncingHeight = await currentSyncingHeight;
final int storedHeight = storedChainHeight;
int _currentNodeHeight = await walletBase?.getNodeHeight() ?? 0;
if (_currentNodeHeight < 1) {
_currentNodeHeight = int64MaxValue;
}
int _currentNodeHeight = await currentNodeHeight;
_fetchTransactionData();
double progress = 0;
try {
progress = (walletBase!.syncStatus!).progress();
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Warning);
}
await _fetchTransactionData();
bool stillSyncing = false;
Logging.instance.log(
"storedHeight: $storedHeight, _currentSyncingHeight: $_currentSyncingHeight, _currentNodeHeight: $_currentNodeHeight",
"storedHeight: $storedHeight, _currentSyncingHeight: $_currentSyncingHeight, _currentNodeHeight: $_currentNodeHeight, progress: $progress, issynced: ${await walletBase!.isConnected()}",
level: LogLevel.Info);
if (storedHeight + 10 < _currentNodeHeight) {
if (progress < 1.0) {
stillSyncing = true;
}
if (_currentSyncingHeight != storedHeight) {
if (_currentSyncingHeight > storedHeight) {
// 0 is returned from monero as I assume an error?????
if (_currentSyncingHeight != 0) {
if (_currentSyncingHeight > 0) {
// 0 failed to fetch current height???
await updateStoredChainHeight(newHeight: _currentSyncingHeight);
}
@ -403,19 +453,11 @@ class MoneroWallet extends CoinServiceAPI {
"Failed to call _generateAddressForChain(0, $curIndex): $e\n$s",
level: LogLevel.Error);
}
//
final newTxData = _fetchTransactionData();
// final feeObj = _getFees();
//
final newTxData = await _fetchTransactionData();
_transactionData = Future(() => newTxData);
//
// this._feeObject = Future(() => feeObj);
// this._utxoData = Future(() => newUtxoData);
//
// await getAllTxsToWatch(await newTxData);
if (isActive || shouldAutoSync) {
timer ??= Timer.periodic(const Duration(seconds: 30), (timer) async {
timer ??= Timer.periodic(const Duration(seconds: 60), (timer) async {
debugPrint("run timer");
//TODO: check for new data and refresh if needed. if monero even needs this
// chain height check currently broken
@ -450,7 +492,7 @@ class MoneroWallet extends CoinServiceAPI {
refreshMutex = false;
return;
}
stopSyncPercentTimer();
await stopSyncPercentTimer();
GlobalEventBus.instance.fire(
WalletSyncStatusChangedEvent(
WalletSyncStatus.synced,
@ -461,7 +503,7 @@ class MoneroWallet extends CoinServiceAPI {
refreshMutex = false;
} catch (error, strace) {
refreshMutex = false;
stopSyncPercentTimer();
await stopSyncPercentTimer();
GlobalEventBus.instance.fire(
NodeConnectionStatusChangedEvent(
NodeConnectionStatus.disconnected,
@ -500,7 +542,7 @@ class MoneroWallet extends CoinServiceAPI {
@override
Future<void> exit() async {
stopSyncPercentTimer();
await stopSyncPercentTimer();
_hasCalledExit = true;
isActive = false;
await walletBase?.save(prioritySave: true);
@ -552,6 +594,7 @@ class MoneroWallet extends CoinServiceAPI {
}
Future<String> _generateAddressForChain(int chain, int index) async {
//
String address = walletBase!.getTransactionAddress(chain, index);
return address;
@ -688,7 +731,6 @@ class MoneroWallet extends CoinServiceAPI {
await walletBase?.connectToNode(
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
await walletBase?.startSync();
walletBase?.getNodeHeight();
await DB.instance
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
@ -806,7 +848,6 @@ class MoneroWallet extends CoinServiceAPI {
String? password;
try {
password = await keysStorage?.getWalletPassword(walletName: _walletId);
debugPrint("password $password");
} catch (e, s) {
debugPrint("Exception was thrown $e $s");
throw Exception("Password not found $e, $s");
@ -999,7 +1040,6 @@ class MoneroWallet extends CoinServiceAPI {
await walletBase?.connectToNode(
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
await walletBase?.rescan(height: credentials.height);
await walletBase?.getNodeHeight();
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from recoverFromMnemonic(): $e\n$s",
@ -1113,13 +1153,12 @@ class MoneroWallet extends CoinServiceAPI {
moneroAutosaveTimer = null;
timer?.cancel();
timer = null;
stopSyncPercentTimer();
await stopSyncPercentTimer();
if (isActive) {
String? password;
try {
password =
await keysStorage?.getWalletPassword(walletName: _walletId);
debugPrint("password $password");
} catch (e, s) {
debugPrint("Exception was thrown $e $s");
throw Exception("Password not found $e, $s");
@ -1131,9 +1170,9 @@ class MoneroWallet extends CoinServiceAPI {
final host = Uri.parse(node.host).host;
await walletBase?.connectToNode(
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
walletBase?.startSync();
await walletBase?.startSync();
}
refresh();
await refresh();
}
this.isActive = isActive;
};

View file

@ -0,0 +1,22 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class CustomMaterialTextSelectionControls
extends MaterialTextSelectionControls {
CustomMaterialTextSelectionControls({required this.onPaste});
ValueChanged<TextSelectionDelegate> onPaste;
@override
Future<void> handlePaste(final TextSelectionDelegate delegate) async {
return onPaste(delegate);
}
}
class CustomCupertinoTextSelectionControls
extends CupertinoTextSelectionControls {
CustomCupertinoTextSelectionControls({required this.onPaste});
ValueChanged<TextSelectionDelegate> onPaste;
@override
Future<void> handlePaste(final TextSelectionDelegate delegate) async {
return onPaste(delegate);
}
}

View file

@ -22,7 +22,8 @@ enum Coin {
firoTestNet,
}
const int kTestNetCoinCount = 3;
// remove firotestnet for now
const int kTestNetCoinCount = 2;
extension CoinExt on Coin {
String get prettyName {

View file

@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.4.31+38
version: 1.4.34+42
environment:
sdk: ">=2.17.0 <3.0.0"

View file

@ -1,14 +1,14 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hive_test/hive_test.dart';
// import 'package:flutter_test/flutter_test.dart';
// import 'package:hive_test/hive_test.dart';
void main() {
setUp(() async {
await setUpTestHive();
});
// no migration to test yet
tearDown(() async {
await tearDownTestHive();
});
// setUp(() async {
// await setUpTestHive();
// });
//
// // no migration to test yet
//
// tearDown(() async {
// await tearDownTestHive();
// });
}

File diff suppressed because it is too large Load diff