mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-11 21:24:31 +00:00
Merge branch 'staging' into rylee-tmp
This commit is contained in:
commit
3764494832
21 changed files with 893 additions and 504 deletions
15
.github/workflows/test.yaml
vendored
15
.github/workflows/test.yaml
vendored
|
@ -1,5 +1,6 @@
|
||||||
|
#should deny
|
||||||
name: Test
|
name: Test
|
||||||
on: [push, pull_request]
|
on: [pull_request]
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
@ -13,6 +14,10 @@ jobs:
|
||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
- name: Checkout submodules
|
- name: Checkout submodules
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
||||||
|
- name: Build Lelantus
|
||||||
|
run: |
|
||||||
|
cd crypto_plugins/flutter_liblelantus/scripts/linux/
|
||||||
|
./build_all.sh
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
- name: Create temp files
|
- name: Create temp files
|
||||||
|
@ -58,7 +63,13 @@ jobs:
|
||||||
# - name: Analyze
|
# - name: Analyze
|
||||||
# run: flutter analyze
|
# run: flutter analyze
|
||||||
- name: Test
|
- 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
|
- name: Delete temp files
|
||||||
run: |
|
run: |
|
||||||
Remove-Item -Path $env:CHANGE_NOW;
|
Remove-Item -Path $env:CHANGE_NOW;
|
||||||
|
|
|
@ -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
|
# Stack Wallet
|
||||||
put details here
|
put details here
|
||||||
|
|
||||||
|
@ -8,13 +10,14 @@ put features here
|
||||||
|
|
||||||
## Build and run
|
## Build and run
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
- Flutter 3.0.5
|
||||||
- Flutter SDK Requirement (>=2.12.0, up until <3.0.0)
|
- Flutter SDK Requirement (>=2.12.0, up until <3.0.0)
|
||||||
- Android/iOS dev setup (Android Studio, xCode and subsequent dependencies)
|
- Android/iOS dev setup (Android Studio, xCode and subsequent dependencies)
|
||||||
|
|
||||||
After that download the project and init the submodules
|
After that download the project and init the submodules
|
||||||
```
|
```
|
||||||
git clone https://github.com/cypherstack/Campfire.git
|
git clone https://github.com/cypherstack/stack_wallet.git
|
||||||
cd Campfire
|
cd stack_wallet
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ linter:
|
||||||
no_leading_underscores_for_local_identifiers: false
|
no_leading_underscores_for_local_identifiers: false
|
||||||
no_leading_underscores_for_library_prefixes: false
|
no_leading_underscores_for_library_prefixes: false
|
||||||
avoid_print: true
|
avoid_print: true
|
||||||
unawaited_futures: false
|
unawaited_futures: true
|
||||||
avoid_double_and_int_checks: false
|
avoid_double_and_int_checks: false
|
||||||
constant_identifier_names: false
|
constant_identifier_names: false
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
|
|
@ -53,6 +53,15 @@ android {
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters "x86_64","armeabi-v7a", "arm64-v8a"
|
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 {
|
signingConfigs {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 78533fa427ffc582b83cb67a766c8d38fac2abd8
|
Subproject commit 6242046217abf47b61d9397ae447632b06f853fa
|
|
@ -1 +1 @@
|
||||||
Subproject commit 771175e87c629ca1d8db7a4417191bd15012d52f
|
Subproject commit cd6f9cf62afcb6c1e55b16a76374a8577d85352f
|
|
@ -449,7 +449,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 37;
|
CURRENT_PROJECT_VERSION = 42;
|
||||||
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -503,7 +503,7 @@
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.4.30;
|
MARKETING_VERSION = 1.4.34;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
@ -633,7 +633,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 37;
|
CURRENT_PROJECT_VERSION = 42;
|
||||||
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -687,7 +687,7 @@
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.4.30;
|
MARKETING_VERSION = 1.4.34;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
@ -709,7 +709,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 37;
|
CURRENT_PROJECT_VERSION = 42;
|
||||||
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
DEVELOPMENT_TEAM = 4DQKUWSG6C;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -763,7 +763,7 @@
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libmonero/cw_shared_external/ios/External/ios/**",
|
||||||
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
"$(PROJECT_DIR)/../crypto_plugins/flutter_libepiccash/ios/libs",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.4.30;
|
MARKETING_VERSION = 1.4.34;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackwallet;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
|
|
@ -176,7 +176,14 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
||||||
|
|
||||||
late final Completer<void> loadingCompleter;
|
late final Completer<void> loadingCompleter;
|
||||||
|
|
||||||
|
bool didLoad = false;
|
||||||
|
|
||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
|
if (didLoad) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
didLoad = true;
|
||||||
|
|
||||||
await DB.instance.init();
|
await DB.instance.init();
|
||||||
|
|
||||||
_notificationsService = ref.read(notificationsProvider);
|
_notificationsService = ref.read(notificationsProvider);
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.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";
|
static const routeName = "/addWallet";
|
||||||
|
|
||||||
final _coins = Coin.values;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<Coin> coins = _coins;
|
List<Coin> coins = [...Coin.values];
|
||||||
if (Platform.isIOS) {
|
coins.remove(Coin.firoTestNet);
|
||||||
coins = _coins;
|
|
||||||
}
|
|
||||||
debugPrint("BUILD: $runtimeType");
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AppBarBackButton(
|
leading: AppBarBackButton(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:math';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:bip39/src/wordlists/english.dart' as bip39wordlist;
|
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/cfcolors.dart';
|
||||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
import 'package:stackwallet/utilities/constants.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/default_nodes.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
|
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
|
||||||
|
@ -70,25 +71,61 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
|
||||||
final List<TextEditingController> _controllers = [];
|
final List<TextEditingController> _controllers = [];
|
||||||
// late final TextEditingController _heightController;
|
|
||||||
final List<FormInputStatus> _inputStatuses = [];
|
final List<FormInputStatus> _inputStatuses = [];
|
||||||
|
|
||||||
// late final FocusNode _heightFocusNode;
|
|
||||||
|
|
||||||
late final BarcodeScannerInterface scanner;
|
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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_seedWordCount = widget.seedWordsLength;
|
_seedWordCount = widget.seedWordsLength;
|
||||||
|
|
||||||
// _heightFocusNode = FocusNode();
|
textSelectionControls = Platform.isIOS
|
||||||
|
? CustomCupertinoTextSelectionControls(onPaste: onControlsPaste)
|
||||||
|
: CustomMaterialTextSelectionControls(onPaste: onControlsPaste);
|
||||||
|
|
||||||
scanner = widget.barcodeScanner;
|
scanner = widget.barcodeScanner;
|
||||||
for (int i = 0; i < _seedWordCount; i++) {
|
for (int i = 0; i < _seedWordCount; i++) {
|
||||||
_controllers.add(TextEditingController());
|
_controllers.add(TextEditingController());
|
||||||
_inputStatuses.add(FormInputStatus.empty);
|
_inputStatuses.add(FormInputStatus.empty);
|
||||||
}
|
}
|
||||||
// _heightController = TextEditingController();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +134,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
||||||
for (var element in _controllers) {
|
for (var element in _controllers) {
|
||||||
element.dispose();
|
element.dispose();
|
||||||
}
|
}
|
||||||
// _heightController.dispose();
|
|
||||||
// _heightFocusNode.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,6 +440,9 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
||||||
_inputStatuses[i] = FormInputStatus.empty;
|
_inputStatuses[i] = FormInputStatus.empty;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller.animateTo(controller.position.maxScrollExtent,
|
||||||
|
duration: const Duration(milliseconds: 300), curve: Curves.decelerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -442,18 +481,8 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
try {
|
try {
|
||||||
// ref
|
|
||||||
// .read(shouldShowLockscreenOnResumeStateProvider.state)
|
|
||||||
// .state = false;
|
|
||||||
final qrResult = await scanner.scan();
|
final qrResult = await scanner.scan();
|
||||||
|
|
||||||
// Future<void>.delayed(
|
|
||||||
// const Duration(seconds: 2),
|
|
||||||
// () => ref
|
|
||||||
// .read(shouldShowLockscreenOnResumeStateProvider.state)
|
|
||||||
// .state = true,
|
|
||||||
// );
|
|
||||||
|
|
||||||
final results =
|
final results =
|
||||||
AddressUtils.decodeQRSeedData(qrResult.rawContent);
|
AddressUtils.decodeQRSeedData(qrResult.rawContent);
|
||||||
|
|
||||||
|
@ -474,9 +503,6 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
// ref
|
|
||||||
// .read(shouldShowLockscreenOnResumeStateProvider.state)
|
|
||||||
// .state = true;
|
|
||||||
// likely failed to get camera permissions
|
// likely failed to get camera permissions
|
||||||
Logging.instance.log("Restore wallet qr scan failed: $e",
|
Logging.instance.log("Restore wallet qr scan failed: $e",
|
||||||
level: LogLevel.Warning);
|
level: LogLevel.Warning);
|
||||||
|
@ -512,9 +538,6 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
||||||
final content = data.text!.trim();
|
final content = data.text!.trim();
|
||||||
final list = content.split(" ");
|
final list = content.split(" ");
|
||||||
_clearAndPopulateMnemonic(list);
|
_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"),
|
_inputStatuses[i - 1], "$i"),
|
||||||
autovalidateMode:
|
autovalidateMode:
|
||||||
AutovalidateMode.onUserInteraction,
|
AutovalidateMode.onUserInteraction,
|
||||||
|
selectionControls:
|
||||||
|
i == 1 ? textSelectionControls : null,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
|
@ -48,7 +48,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
|
||||||
ref.refresh(addressBookFilterProvider);
|
ref.refresh(addressBookFilterProvider);
|
||||||
|
|
||||||
if (widget.coin == null) {
|
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;
|
bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ class _AddressBookFilterViewState extends ConsumerState<AddressBookFilterView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
final coins = Coin.values;
|
List<Coin> coins = [...Coin.values];
|
||||||
|
coins.remove(Coin.firoTestNet);
|
||||||
|
|
||||||
bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
|
bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ class CoinSelectSheet extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final maxHeight = MediaQuery.of(context).size.height * 0.60;
|
final maxHeight = MediaQuery.of(context).size.height * 0.60;
|
||||||
|
var coins_ = [...Coin.values];
|
||||||
|
coins_.remove(Coin.firoTestNet);
|
||||||
return Container(
|
return Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: CFColors.white,
|
color: CFColors.white,
|
||||||
|
@ -68,10 +70,10 @@ class CoinSelectSheet extends StatelessWidget {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: showTestNet
|
itemCount: showTestNet
|
||||||
? Coin.values.length
|
? coins_.length
|
||||||
: Coin.values.length - kTestNetCoinCount,
|
: coins_.length - kTestNetCoinCount,
|
||||||
itemBuilder: (builderContext, index) {
|
itemBuilder: (builderContext, index) {
|
||||||
final coin = Coin.values[index];
|
final coin = coins_[index];
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
child: RawMaterialButton(
|
child: RawMaterialButton(
|
||||||
|
|
|
@ -23,11 +23,12 @@ class ManageNodesView extends ConsumerStatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ManageNodesViewState extends ConsumerState<ManageNodesView> {
|
class _ManageNodesViewState extends ConsumerState<ManageNodesView> {
|
||||||
List<Coin> _coins = Coin.values;
|
List<Coin> _coins = [...Coin.values];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_coins = _coins.toList();
|
_coins = _coins.toList();
|
||||||
|
_coins.remove(Coin.firoTestNet);
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -726,7 +726,7 @@ Future<String> _getMintScriptWrapper(
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _setTestnetWrapper(bool isTestnet) async {
|
Future<void> _setTestnetWrapper(bool isTestnet) async {
|
||||||
setTestnet(isTestnet);
|
// setTestnet(isTestnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a single instance of a firo wallet
|
/// Handles a single instance of a firo wallet
|
||||||
|
@ -2893,6 +2893,7 @@ class FiroWallet extends CoinServiceAPI {
|
||||||
}
|
}
|
||||||
if (Platform.environment["FLUTTER_TEST"] == "true" || integrationTestFlag) {
|
if (Platform.environment["FLUTTER_TEST"] == "true" || integrationTestFlag) {
|
||||||
perBatch = 10;
|
perBatch = 10;
|
||||||
|
numberOfThreads = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
final receiveDerivationsString =
|
final receiveDerivationsString =
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:cw_core/monero_amount_format.dart';
|
||||||
import 'package:cw_core/monero_transaction_priority.dart';
|
import 'package:cw_core/monero_transaction_priority.dart';
|
||||||
import 'package:cw_core/node.dart';
|
import 'package:cw_core/node.dart';
|
||||||
import 'package:cw_core/pending_transaction.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/transaction_direction.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/wallet_credentials.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_libmonero/view_model/send/output.dart' as monero_output;
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:stackwallet/hive/db.dart';
|
import 'package:stackwallet/hive/db.dart';
|
||||||
|
@ -121,10 +123,10 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
||||||
|
|
||||||
// TODO: is this sync call needed? Do we need to notify ui here?
|
// TODO: is this sync call needed? Do we need to notify ui here?
|
||||||
walletBase?.startSync();
|
await walletBase?.startSync();
|
||||||
|
|
||||||
if (shouldRefresh) {
|
if (shouldRefresh) {
|
||||||
refresh();
|
await refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,13 +144,37 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||||
|
|
||||||
Future<int> get currentNodeHeight async {
|
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
|
final cachedHeight = DB.instance
|
||||||
.get<dynamic>(boxName: walletId, key: "storedNodeHeight") as int? ??
|
.get<dynamic>(boxName: walletId, key: "storedNodeHeight") as int? ??
|
||||||
0;
|
0;
|
||||||
|
|
||||||
if (currentHeight > cachedHeight) {
|
if (currentHeight > cachedHeight && currentHeight != int64MaxValue) {
|
||||||
DB.instance.put<dynamic>(
|
await DB.instance.put<dynamic>(
|
||||||
boxName: walletId, key: "storedNodeHeight", value: currentHeight);
|
boxName: walletId, key: "storedNodeHeight", value: currentHeight);
|
||||||
return currentHeight;
|
return currentHeight;
|
||||||
} else {
|
} 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
|
//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 =
|
final cachedHeight =
|
||||||
DB.instance.get<dynamic>(boxName: walletId, key: "storedSyncingHeight")
|
DB.instance.get<dynamic>(boxName: walletId, key: "storedSyncingHeight")
|
||||||
as int? ??
|
as int? ??
|
||||||
0;
|
0;
|
||||||
|
|
||||||
if (syncingHeight > cachedHeight) {
|
if (syncingHeight > cachedHeight) {
|
||||||
DB.instance.put<dynamic>(
|
await DB.instance.put<dynamic>(
|
||||||
boxName: walletId, key: "storedSyncingHeight", value: syncingHeight);
|
boxName: walletId, key: "storedSyncingHeight", value: syncingHeight);
|
||||||
return syncingHeight;
|
return syncingHeight;
|
||||||
} else {
|
} else {
|
||||||
return cachedHeight;
|
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 {
|
Future<void> updateStoredChainHeight({required int newHeight}) async {
|
||||||
|
@ -270,63 +301,78 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
|
|
||||||
Timer? syncPercentTimer;
|
Timer? syncPercentTimer;
|
||||||
|
|
||||||
void stopSyncPercentTimer() {
|
Mutex syncHeightMutex = Mutex();
|
||||||
|
Future<void> stopSyncPercentTimer() async {
|
||||||
syncPercentTimer?.cancel();
|
syncPercentTimer?.cancel();
|
||||||
syncPercentTimer = null;
|
syncPercentTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void startSyncPercentTimer() {
|
Future<void> startSyncPercentTimer() async {
|
||||||
|
if (syncPercentTimer != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
syncPercentTimer?.cancel();
|
syncPercentTimer?.cancel();
|
||||||
GlobalEventBus.instance
|
GlobalEventBus.instance
|
||||||
.fire(RefreshPercentChangedEvent(highestPercentCached, walletId));
|
.fire(RefreshPercentChangedEvent(highestPercentCached, walletId));
|
||||||
syncPercentTimer = Timer.periodic(const Duration(seconds: 3), (_) async {
|
syncPercentTimer = Timer.periodic(const Duration(seconds: 30), (_) async {
|
||||||
// int restoreheight = walletBase!.walletInfo.restoreHeight ?? 0;
|
if (syncHeightMutex.isLocked) {
|
||||||
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,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
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
|
final int blocksRemaining = _currentHeight - _height;
|
||||||
// int64MaxValue is NOT the best value to use here
|
|
||||||
if (_currentHeight < 1) {
|
|
||||||
_currentHeight = int64MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_height < 1) {
|
GlobalEventBus.instance
|
||||||
_height = 1;
|
.fire(BlocksRemainingEvent(blocksRemaining, walletId));
|
||||||
}
|
|
||||||
|
|
||||||
double restorePercent = (_height / _currentHeight).clamp(0.0, 1.0);
|
if (progress == 1 && _currentHeight > 0 && _height > 0) {
|
||||||
double highestPercent = highestPercentCached;
|
await stopSyncPercentTimer();
|
||||||
|
GlobalEventBus.instance.fire(
|
||||||
|
WalletSyncStatusChangedEvent(
|
||||||
|
WalletSyncStatus.synced,
|
||||||
|
walletId,
|
||||||
|
coin,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Logging.instance.log(
|
// for some reason this can be 0 which screws up the percent calculation
|
||||||
"currentSyncingHeight: $_height, nodeHeight: $_currentHeight, restorePercent: $restorePercent, highestPercentCached: $highestPercentCached",
|
// int64MaxValue is NOT the best value to use here
|
||||||
level: LogLevel.Info);
|
if (_currentHeight < 1) {
|
||||||
|
_currentHeight = int64MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
if (restorePercent > 0 && restorePercent <= 1) {
|
if (_height < 1) {
|
||||||
if (restorePercent > highestPercent) {
|
_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;
|
highestPercent = restorePercent;
|
||||||
highestPercentCached = restorePercent;
|
highestPercentCached = restorePercent;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
GlobalEventBus.instance
|
GlobalEventBus.instance
|
||||||
.fire(RefreshPercentChangedEvent(highestPercent, walletId));
|
.fire(RefreshPercentChangedEvent(highestPercent, walletId));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +402,7 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
startSyncPercentTimer();
|
await startSyncPercentTimer();
|
||||||
GlobalEventBus.instance.fire(
|
GlobalEventBus.instance.fire(
|
||||||
WalletSyncStatusChangedEvent(
|
WalletSyncStatusChangedEvent(
|
||||||
WalletSyncStatus.syncing,
|
WalletSyncStatus.syncing,
|
||||||
|
@ -365,26 +411,30 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final int _currentSyncingHeight = currentSyncingHeight;
|
final int _currentSyncingHeight = await currentSyncingHeight;
|
||||||
final int storedHeight = storedChainHeight;
|
final int storedHeight = storedChainHeight;
|
||||||
int _currentNodeHeight = await walletBase?.getNodeHeight() ?? 0;
|
int _currentNodeHeight = await currentNodeHeight;
|
||||||
if (_currentNodeHeight < 1) {
|
|
||||||
_currentNodeHeight = int64MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_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;
|
bool stillSyncing = false;
|
||||||
Logging.instance.log(
|
Logging.instance.log(
|
||||||
"storedHeight: $storedHeight, _currentSyncingHeight: $_currentSyncingHeight, _currentNodeHeight: $_currentNodeHeight",
|
"storedHeight: $storedHeight, _currentSyncingHeight: $_currentSyncingHeight, _currentNodeHeight: $_currentNodeHeight, progress: $progress, issynced: ${await walletBase!.isConnected()}",
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
if (storedHeight + 10 < _currentNodeHeight) {
|
|
||||||
|
if (progress < 1.0) {
|
||||||
stillSyncing = true;
|
stillSyncing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_currentSyncingHeight != storedHeight) {
|
if (_currentSyncingHeight > storedHeight) {
|
||||||
// 0 is returned from monero as I assume an error?????
|
// 0 is returned from monero as I assume an error?????
|
||||||
if (_currentSyncingHeight != 0) {
|
if (_currentSyncingHeight > 0) {
|
||||||
// 0 failed to fetch current height???
|
// 0 failed to fetch current height???
|
||||||
await updateStoredChainHeight(newHeight: _currentSyncingHeight);
|
await updateStoredChainHeight(newHeight: _currentSyncingHeight);
|
||||||
}
|
}
|
||||||
|
@ -403,19 +453,11 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
"Failed to call _generateAddressForChain(0, $curIndex): $e\n$s",
|
"Failed to call _generateAddressForChain(0, $curIndex): $e\n$s",
|
||||||
level: LogLevel.Error);
|
level: LogLevel.Error);
|
||||||
}
|
}
|
||||||
//
|
final newTxData = await _fetchTransactionData();
|
||||||
final newTxData = _fetchTransactionData();
|
|
||||||
// final feeObj = _getFees();
|
|
||||||
//
|
|
||||||
_transactionData = Future(() => newTxData);
|
_transactionData = Future(() => newTxData);
|
||||||
//
|
|
||||||
// this._feeObject = Future(() => feeObj);
|
|
||||||
// this._utxoData = Future(() => newUtxoData);
|
|
||||||
//
|
|
||||||
// await getAllTxsToWatch(await newTxData);
|
|
||||||
|
|
||||||
if (isActive || shouldAutoSync) {
|
if (isActive || shouldAutoSync) {
|
||||||
timer ??= Timer.periodic(const Duration(seconds: 30), (timer) async {
|
timer ??= Timer.periodic(const Duration(seconds: 60), (timer) async {
|
||||||
debugPrint("run timer");
|
debugPrint("run timer");
|
||||||
//TODO: check for new data and refresh if needed. if monero even needs this
|
//TODO: check for new data and refresh if needed. if monero even needs this
|
||||||
// chain height check currently broken
|
// chain height check currently broken
|
||||||
|
@ -450,7 +492,7 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
refreshMutex = false;
|
refreshMutex = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stopSyncPercentTimer();
|
await stopSyncPercentTimer();
|
||||||
GlobalEventBus.instance.fire(
|
GlobalEventBus.instance.fire(
|
||||||
WalletSyncStatusChangedEvent(
|
WalletSyncStatusChangedEvent(
|
||||||
WalletSyncStatus.synced,
|
WalletSyncStatus.synced,
|
||||||
|
@ -461,7 +503,7 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
refreshMutex = false;
|
refreshMutex = false;
|
||||||
} catch (error, strace) {
|
} catch (error, strace) {
|
||||||
refreshMutex = false;
|
refreshMutex = false;
|
||||||
stopSyncPercentTimer();
|
await stopSyncPercentTimer();
|
||||||
GlobalEventBus.instance.fire(
|
GlobalEventBus.instance.fire(
|
||||||
NodeConnectionStatusChangedEvent(
|
NodeConnectionStatusChangedEvent(
|
||||||
NodeConnectionStatus.disconnected,
|
NodeConnectionStatus.disconnected,
|
||||||
|
@ -500,7 +542,7 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> exit() async {
|
Future<void> exit() async {
|
||||||
stopSyncPercentTimer();
|
await stopSyncPercentTimer();
|
||||||
_hasCalledExit = true;
|
_hasCalledExit = true;
|
||||||
isActive = false;
|
isActive = false;
|
||||||
await walletBase?.save(prioritySave: true);
|
await walletBase?.save(prioritySave: true);
|
||||||
|
@ -552,6 +594,7 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> _generateAddressForChain(int chain, int index) async {
|
Future<String> _generateAddressForChain(int chain, int index) async {
|
||||||
|
//
|
||||||
String address = walletBase!.getTransactionAddress(chain, index);
|
String address = walletBase!.getTransactionAddress(chain, index);
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
|
@ -688,7 +731,6 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
await walletBase?.connectToNode(
|
await walletBase?.connectToNode(
|
||||||
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
||||||
await walletBase?.startSync();
|
await walletBase?.startSync();
|
||||||
walletBase?.getNodeHeight();
|
|
||||||
await DB.instance
|
await DB.instance
|
||||||
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
|
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
|
||||||
|
|
||||||
|
@ -806,7 +848,6 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
String? password;
|
String? password;
|
||||||
try {
|
try {
|
||||||
password = await keysStorage?.getWalletPassword(walletName: _walletId);
|
password = await keysStorage?.getWalletPassword(walletName: _walletId);
|
||||||
debugPrint("password $password");
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
debugPrint("Exception was thrown $e $s");
|
debugPrint("Exception was thrown $e $s");
|
||||||
throw Exception("Password not found $e, $s");
|
throw Exception("Password not found $e, $s");
|
||||||
|
@ -999,7 +1040,6 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
await walletBase?.connectToNode(
|
await walletBase?.connectToNode(
|
||||||
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
||||||
await walletBase?.rescan(height: credentials.height);
|
await walletBase?.rescan(height: credentials.height);
|
||||||
await walletBase?.getNodeHeight();
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logging.instance.log(
|
Logging.instance.log(
|
||||||
"Exception rethrown from recoverFromMnemonic(): $e\n$s",
|
"Exception rethrown from recoverFromMnemonic(): $e\n$s",
|
||||||
|
@ -1113,13 +1153,12 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
moneroAutosaveTimer = null;
|
moneroAutosaveTimer = null;
|
||||||
timer?.cancel();
|
timer?.cancel();
|
||||||
timer = null;
|
timer = null;
|
||||||
stopSyncPercentTimer();
|
await stopSyncPercentTimer();
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
String? password;
|
String? password;
|
||||||
try {
|
try {
|
||||||
password =
|
password =
|
||||||
await keysStorage?.getWalletPassword(walletName: _walletId);
|
await keysStorage?.getWalletPassword(walletName: _walletId);
|
||||||
debugPrint("password $password");
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
debugPrint("Exception was thrown $e $s");
|
debugPrint("Exception was thrown $e $s");
|
||||||
throw Exception("Password not found $e, $s");
|
throw Exception("Password not found $e, $s");
|
||||||
|
@ -1131,9 +1170,9 @@ class MoneroWallet extends CoinServiceAPI {
|
||||||
final host = Uri.parse(node.host).host;
|
final host = Uri.parse(node.host).host;
|
||||||
await walletBase?.connectToNode(
|
await walletBase?.connectToNode(
|
||||||
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
|
||||||
walletBase?.startSync();
|
await walletBase?.startSync();
|
||||||
}
|
}
|
||||||
refresh();
|
await refresh();
|
||||||
}
|
}
|
||||||
this.isActive = isActive;
|
this.isActive = isActive;
|
||||||
};
|
};
|
||||||
|
|
22
lib/utilities/custom_text_selection_controls.dart
Normal file
22
lib/utilities/custom_text_selection_controls.dart
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,8 @@ enum Coin {
|
||||||
firoTestNet,
|
firoTestNet,
|
||||||
}
|
}
|
||||||
|
|
||||||
const int kTestNetCoinCount = 3;
|
// remove firotestnet for now
|
||||||
|
const int kTestNetCoinCount = 2;
|
||||||
|
|
||||||
extension CoinExt on Coin {
|
extension CoinExt on Coin {
|
||||||
String get prettyName {
|
String get prettyName {
|
||||||
|
|
|
@ -11,7 +11,7 @@ description: Stack Wallet
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.4.31+38
|
version: 1.4.34+42
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
// import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:hive_test/hive_test.dart';
|
// import 'package:hive_test/hive_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
setUp(() async {
|
// setUp(() async {
|
||||||
await setUpTestHive();
|
// await setUpTestHive();
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
// no migration to test yet
|
// // no migration to test yet
|
||||||
|
//
|
||||||
tearDown(() async {
|
// tearDown(() async {
|
||||||
await tearDownTestHive();
|
// await tearDownTestHive();
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue