Merge pull request #341 from cypherstack/paynyms

Paynyms
This commit is contained in:
Diego Salazar 2023-02-09 17:01:10 -07:00 committed by GitHub
commit 61e0c66e04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 3630 additions and 3041 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -17,6 +17,7 @@ import 'package:hive_flutter/hive_flutter.dart';
import 'package:isar/isar.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:path_provider/path_provider.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart';
@ -65,8 +66,6 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:window_size/window_size.dart';
import 'db/main_db.dart';
final openedFromSWBFileStringStateProvider =
StateProvider<String?>((ref) => null);
@ -290,10 +289,6 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
// TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet
// unawaited(_nodeService.updateCommunityNodes());
print("================================================");
print("${ref.read(prefsChangeNotifierProvider).externalCalls}");
print("${await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()}");
print("================================================");
// run without awaiting
if (ref.read(prefsChangeNotifierProvider).externalCalls &&
await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) {

View file

@ -0,0 +1,40 @@
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:tuple/tuple.dart';
class AggregateCurrency {
final Map<String, Currency?> _map = {};
AggregateCurrency(
{required List<Tuple2<String, Currency>> exchangeCurrencyPairs}) {
assert(exchangeCurrencyPairs.isNotEmpty);
for (final item in exchangeCurrencyPairs) {
_map[item.item1] = item.item2;
}
}
Currency? forExchange(String exchangeName) {
return _map[exchangeName];
}
String get ticker => _map.values.first!.ticker;
String get name => _map.values.first!.name;
String get image => _map.values.first!.image;
SupportedRateType get rateType => _map.values.first!.rateType;
bool get isStackCoin => _map.values.first!.isStackCoin;
@override
String toString() {
String str = "AggregateCurrency: {";
for (final key in _map.keys) {
str += " $key: ${_map[key]},";
}
str += " }";
return str;
}
}

View file

@ -1,14 +1,11 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
class ExchangeFormState extends ChangeNotifier {
@ -53,15 +50,15 @@ class ExchangeFormState extends ChangeNotifier {
//
}
Currency? _sendCurrency;
Currency? get sendCurrency => _sendCurrency;
AggregateCurrency? _sendCurrency;
AggregateCurrency? get sendCurrency => _sendCurrency;
// set sendCurrency(Currency? sendCurrency) {
// _sendCurrency = sendCurrency;
// //
// }
Currency? _receiveCurrency;
Currency? get receiveCurrency => _receiveCurrency;
AggregateCurrency? _receiveCurrency;
AggregateCurrency? get receiveCurrency => _receiveCurrency;
// set receiveCurrency(Currency? receiveCurrency) {
// _receiveCurrency = receiveCurrency;
// //
@ -113,8 +110,8 @@ class ExchangeFormState extends ChangeNotifier {
receiveAmount != null &&
rate != null &&
rate! >= Decimal.zero &&
exchange.name == sendCurrency!.exchangeName &&
exchange.name == receiveCurrency!.exchangeName &&
sendCurrency!.forExchange(exchange.name) != null &&
receiveCurrency!.forExchange(exchange.name) != null &&
warning.isEmpty;
}
@ -156,73 +153,6 @@ class ExchangeFormState extends ChangeNotifier {
}) async {
_exchange = exchange;
if (shouldUpdateData) {
if (_sendCurrency != null) {
_sendCurrency = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(exchange.name)
.filter()
.tickerEqualTo(_sendCurrency!.ticker)
.and()
.group((q) => exchangeRateType == ExchangeRateType.fixed
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.findFirst();
}
if (_sendCurrency == null) {
switch (exchange.name) {
case ChangeNowExchange.exchangeName:
_sendCurrency = _cachedSendCN;
break;
case MajesticBankExchange.exchangeName:
_sendCurrency = _cachedSendMB;
break;
}
}
if (_receiveCurrency != null) {
_receiveCurrency = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(exchange.name)
.filter()
.tickerEqualTo(_receiveCurrency!.ticker)
.and()
.group((q) => exchangeRateType == ExchangeRateType.fixed
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.findFirst();
}
if (_receiveCurrency == null) {
switch (exchange.name) {
case ChangeNowExchange.exchangeName:
_receiveCurrency = _cachedReceivingCN;
break;
case MajesticBankExchange.exchangeName:
_receiveCurrency = _cachedReceivingMB;
break;
}
}
_updateCachedCurrencies(
exchangeName: exchange.name,
send: _sendCurrency,
receiving: _receiveCurrency,
);
await _updateRangesAndEstimate(
shouldNotifyListeners: false,
);
@ -233,14 +163,9 @@ class ExchangeFormState extends ChangeNotifier {
}
}
void setCurrencies(Currency from, Currency to) {
void setCurrencies(AggregateCurrency from, AggregateCurrency to) {
_sendCurrency = from;
_receiveCurrency = to;
_updateCachedCurrencies(
exchangeName: exchange.name,
send: _sendCurrency,
receiving: _receiveCurrency,
);
}
void reset({
@ -316,7 +241,7 @@ class ExchangeFormState extends ChangeNotifier {
}
Future<void> updateSendCurrency(
Currency sendCurrency,
AggregateCurrency sendCurrency,
bool shouldNotifyListeners,
) async {
try {
@ -324,12 +249,6 @@ class ExchangeFormState extends ChangeNotifier {
_minSendAmount = null;
_maxSendAmount = null;
_updateCachedCurrencies(
exchangeName: exchange.name,
send: _sendCurrency,
receiving: _receiveCurrency,
);
if (_receiveCurrency == null) {
_rate = null;
} else {
@ -346,7 +265,7 @@ class ExchangeFormState extends ChangeNotifier {
}
Future<void> updateReceivingCurrency(
Currency receiveCurrency,
AggregateCurrency receiveCurrency,
bool shouldNotifyListeners,
) async {
try {
@ -354,12 +273,6 @@ class ExchangeFormState extends ChangeNotifier {
_minReceiveAmount = null;
_maxReceiveAmount = null;
_updateCachedCurrencies(
exchangeName: exchange.name,
send: _sendCurrency,
receiving: _receiveCurrency,
);
if (_sendCurrency == null) {
_rate = null;
} else {
@ -387,16 +300,10 @@ class ExchangeFormState extends ChangeNotifier {
_minReceiveAmount = null;
_maxReceiveAmount = null;
final Currency? tmp = sendCurrency;
final AggregateCurrency? tmp = sendCurrency;
_sendCurrency = receiveCurrency;
_receiveCurrency = tmp;
_updateCachedCurrencies(
exchangeName: exchange.name,
send: _sendCurrency,
receiving: _receiveCurrency,
);
await _updateRangesAndEstimate(
shouldNotifyListeners: false,
);
@ -418,6 +325,29 @@ class ExchangeFormState extends ChangeNotifier {
required bool shouldNotifyListeners,
}) async {
try {
switch (exchange.name) {
case ChangeNowExchange.exchangeName:
if (!_exchangeSupported(
exchangeName: exchange.name,
sendCurrency: sendCurrency,
receiveCurrency: receiveCurrency,
exchangeRateType: exchangeRateType,
)) {
_exchange = MajesticBankExchange.instance;
}
break;
case MajesticBankExchange.exchangeName:
if (!_exchangeSupported(
exchangeName: exchange.name,
sendCurrency: sendCurrency,
receiveCurrency: receiveCurrency,
exchangeRateType: exchangeRateType,
)) {
_exchange = ChangeNowExchange.instance;
}
break;
}
await _updateRanges(shouldNotifyListeners: false);
await _updateEstimate(shouldNotifyListeners: false);
if (shouldNotifyListeners) {
@ -542,33 +472,30 @@ class ExchangeFormState extends ChangeNotifier {
//============================================================================
Currency? _cachedReceivingMB;
Currency? _cachedSendMB;
Currency? _cachedReceivingCN;
Currency? _cachedSendCN;
void _updateCachedCurrencies({
required String exchangeName,
required Currency? send,
required Currency? receiving,
}) {
switch (exchangeName) {
case ChangeNowExchange.exchangeName:
_cachedSendCN = send ?? _cachedSendCN;
_cachedReceivingCN = receiving ?? _cachedReceivingCN;
break;
case MajesticBankExchange.exchangeName:
_cachedSendMB = send ?? _cachedSendMB;
_cachedReceivingMB = receiving ?? _cachedReceivingMB;
break;
}
}
void _notify() {
debugPrint("ExFState NOTIFY: ${toString()}");
notifyListeners();
}
bool _exchangeSupported({
required String exchangeName,
required AggregateCurrency? sendCurrency,
required AggregateCurrency? receiveCurrency,
required ExchangeRateType exchangeRateType,
}) {
final send = sendCurrency?.forExchange(exchangeName);
if (send == null) return false;
final rcv = receiveCurrency?.forExchange(exchangeName);
if (rcv == null) return false;
if (exchangeRateType == ExchangeRateType.fixed) {
return send.supportsFixedRate && rcv.supportsFixedRate;
} else {
return send.supportsEstimatedRate && rcv.supportsEstimatedRate;
}
}
@override
String toString() {
return "{"

View file

@ -1,7 +1,7 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/foundation.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
class IncompleteExchangeModel extends ChangeNotifier {
final String sendTicker;
@ -15,6 +15,7 @@ class IncompleteExchangeModel extends ChangeNotifier {
final ExchangeRateType rateType;
final bool reversed;
final bool walletInitiated;
String? _recipientAddress;
@ -68,6 +69,7 @@ class IncompleteExchangeModel extends ChangeNotifier {
required this.receiveAmount,
required this.rateType,
required this.reversed,
required this.walletInitiated,
String? rateId,
}) : _rateId = rateId;
}

View file

@ -44,6 +44,12 @@ class Currency {
@Index()
final bool isStackCoin;
@ignore
bool get supportsFixedRate => rateType == SupportedRateType.fixed || rateType == SupportedRateType.both;
@ignore
bool get supportsEstimatedRate => rateType == SupportedRateType.estimated || rateType == SupportedRateType.both;
Currency({
required this.exchangeName,
required this.ticker,

View file

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:isar/isar.dart';
import 'package:stackwallet/exceptions/address/address_exception.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/crypto_currency_address.dart';
@ -71,6 +73,45 @@ class Address extends CryptoCurrencyAddress {
"derivationPath: $derivationPath, "
"otherData: $otherData, "
"}";
String toJsonString() {
final Map<String, dynamic> result = {
"walletId": walletId,
"value": value,
"publicKey": publicKey,
"derivationIndex": derivationIndex,
"type": type.name,
"subType": subType.name,
"derivationPath": derivationPath?.value,
"otherData": otherData,
};
return jsonEncode(result);
}
static Address fromJsonString(
String jsonString, {
String? overrideWalletId,
}) {
final json = jsonDecode(jsonString);
final derivationPathString = json["derivationPath"] as String?;
final DerivationPath? derivationPath =
derivationPathString == null ? null : DerivationPath();
if (derivationPath != null) {
derivationPath.value = derivationPathString!;
}
return Address(
walletId: overrideWalletId ?? json["walletId"] as String,
value: json["value"] as String,
publicKey: List<int>.from(json["publicKey"] as List),
derivationIndex: json["derivationIndex"] as int,
derivationPath: derivationPath,
type: AddressType.values.byName(json["type"] as String),
subType: AddressSubType.values.byName(json["subType"] as String),
otherData: json["otherData"] as String?,
);
}
}
// do not modify

View file

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:isar/isar.dart';
part 'input.g.dart';
@ -30,4 +32,32 @@ class Input {
late final int? sequence;
late final String? innerRedeemScriptAsm;
String toJsonString() {
final Map<String, dynamic> result = {
"txid": txid,
"vout": vout,
"scriptSig": scriptSig,
"scriptSigAsm": scriptSigAsm,
"witness": witness,
"isCoinbase": isCoinbase,
"sequence": sequence,
"innerRedeemScriptAsm": innerRedeemScriptAsm,
};
return jsonEncode(result);
}
static Input fromJsonString(String jsonString) {
final json = jsonDecode(jsonString);
return Input(
txid: json["txid"] as String,
vout: json["vout"] as int,
scriptSig: json["scriptSig"] as String?,
scriptSigAsm: json["scriptSigAsm"] as String?,
witness: json["witness"] as String?,
isCoinbase: json["isCoinbase"] as bool?,
sequence: json["sequence"] as int?,
innerRedeemScriptAsm: json["innerRedeemScriptAsm"] as String?,
);
}
}

View file

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:isar/isar.dart';
part 'output.g.dart';
@ -21,4 +23,26 @@ class Output {
late final String scriptPubKeyAddress;
late final int value;
String toJsonString() {
final Map<String, dynamic> result = {
"scriptPubKey": scriptPubKey,
"scriptPubKeyAsm": scriptPubKeyAsm,
"scriptPubKeyType": scriptPubKeyType,
"scriptPubKeyAddress": scriptPubKeyAddress,
"value": value,
};
return jsonEncode(result);
}
static Output fromJsonString(String jsonString) {
final json = jsonDecode(jsonString);
return Output(
scriptPubKey: json["scriptPubKey"] as String?,
scriptPubKeyAsm: json["scriptPubKeyAsm"] as String?,
scriptPubKeyType: json["scriptPubKeyType"] as String?,
scriptPubKeyAddress: json["scriptPubKeyAddress"] as String,
value: json["value"] as int,
);
}
}

View file

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:math';
import 'package:isar/isar.dart';
@ -133,6 +134,60 @@ class Transaction {
"inputsLength: ${inputs.length}, "
"outputsLength: ${outputs.length}, "
"}";
String toJsonString() {
final Map<String, dynamic> result = {
"walletId": walletId,
"txid": txid,
"timestamp": timestamp,
"type": type.name,
"subType": subType.name,
"amount": amount,
"fee": fee,
"height": height,
"isCancelled": isCancelled,
"isLelantus": isLelantus,
"slateId": slateId,
"otherData": otherData,
"address": address.value?.toJsonString(),
"inputs": inputs.map((e) => e.toJsonString()).toList(),
"outputs": outputs.map((e) => e.toJsonString()).toList(),
};
return jsonEncode(result);
}
static Tuple2<Transaction, Address?> fromJsonString(
String jsonString, {
String? overrideWalletId,
}) {
final json = jsonDecode(jsonString);
final transaction = Transaction(
walletId: overrideWalletId ?? json["walletId"] as String,
txid: json["txid"] as String,
timestamp: json["timestamp"] as int,
type: TransactionType.values.byName(json["type"] as String),
subType: TransactionSubType.values.byName(json["subType"] as String),
amount: json["amount"] as int,
fee: json["fee"] as int,
height: json["height"] as int?,
isCancelled: json["isCancelled"] as bool,
isLelantus: json["isLelantus"] as bool?,
slateId: json["slateId"] as String?,
otherData: json["otherData"] as String?,
inputs: List<String>.from(json["inputs"] as List)
.map((e) => Input.fromJsonString(e))
.toList(),
outputs: List<String>.from(json["outputs"] as List)
.map((e) => Output.fromJsonString(e))
.toList(),
);
if (json["address"] == null) {
return Tuple2(transaction, null);
} else {
final address = Address.fromJsonString(json["address"] as String);
return Tuple2(transaction, address);
}
}
}
// Used in Isar db and stored there as int indexes so adding/removing values

View file

@ -20,10 +20,13 @@ import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
import 'package:stackwallet/widgets/expandable.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:tuple/tuple.dart';
class RestoreOptionsView extends ConsumerStatefulWidget {
@ -49,10 +52,17 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
late TextEditingController _dateController;
late FocusNode textFieldFocusNode;
late final FocusNode passwordFocusNode;
late final TextEditingController passwordController;
final bool _nextEnabled = true;
DateTime _restoreFromDate = DateTime.fromMillisecondsSinceEpoch(0);
late final Color baseColor;
bool hidePassword = true;
bool _expandedAdavnced = false;
bool get supportsMnemonicPassphrase =>
!(coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash);
@override
void initState() {
@ -63,6 +73,8 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
_dateController = TextEditingController();
textFieldFocusNode = FocusNode();
passwordController = TextEditingController();
passwordFocusNode = FocusNode();
super.initState();
}
@ -71,6 +83,8 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
void dispose() {
_dateController.dispose();
textFieldFocusNode.dispose();
passwordController.dispose();
passwordFocusNode.dispose();
super.dispose();
}
@ -132,11 +146,12 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
if (mounted) {
await Navigator.of(context).pushNamed(
RestoreWalletView.routeName,
arguments: Tuple4(
arguments: Tuple5(
walletName,
coin,
ref.read(mnemonicWordCountStateProvider.state).state,
_restoreFromDate,
passwordController.text,
),
);
}
@ -186,8 +201,6 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
await Future<void>.delayed(const Duration(milliseconds: 125));
}
final now = DateTime.now();
final date = await showRoundedDatePicker(
context: context,
initialDate: DateTime.now(),
@ -441,6 +454,120 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
MobileMnemonicLengthSelector(
chooseMnemonicLength: chooseMnemonicLength,
),
if (supportsMnemonicPassphrase)
SizedBox(
height: isDesktop ? 24 : 16,
),
if (supportsMnemonicPassphrase)
Expandable(
onExpandChanged: (state) {
setState(() {
_expandedAdavnced = state == ExpandableState.expanded;
});
},
header: Container(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 16,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Advanced",
style: isDesktop
? STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
)
: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
SvgPicture.asset(
_expandedAdavnced
? Assets.svg.chevronUp
: Assets.svg.chevronDown,
width: 12,
height: 6,
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
],
),
),
),
body: Container(
color: Colors.transparent,
child: ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
key: const Key("mnemonicPassphraseFieldKey1"),
focusNode: passwordFocusNode,
controller: passwordController,
style: isDesktop
? STextStyles.desktopTextMedium(context).copyWith(
height: 2,
)
: STextStyles.field(context),
obscureText: hidePassword,
enableSuggestions: false,
autocorrect: false,
decoration: standardInputDecoration(
"Recovery phrase password",
passwordFocusNode,
context,
).copyWith(
suffixIcon: UnconstrainedBox(
child: ConditionalParent(
condition: isDesktop,
builder: (child) => SizedBox(
height: 70,
child: child,
),
child: Row(
children: [
SizedBox(
width: isDesktop ? 24 : 16,
),
GestureDetector(
key: const Key(
"mnemonicPassphraseFieldShowPasswordButtonKey"),
onTap: () async {
setState(() {
hidePassword = !hidePassword;
});
},
child: SvgPicture.asset(
hidePassword
? Assets.svg.eye
: Assets.svg.eyeSlash,
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
width: isDesktop ? 24 : 16,
height: isDesktop ? 24 : 16,
),
),
const SizedBox(
width: 12,
),
],
),
),
),
),
),
),
),
),
if (!isDesktop)
const Spacer(
flex: 3,

View file

@ -54,6 +54,7 @@ class RestoreWalletView extends ConsumerStatefulWidget {
required this.walletName,
required this.coin,
required this.seedWordsLength,
required this.mnemonicPassphrase,
required this.restoreFromDate,
this.barcodeScanner = const BarcodeScannerWrapper(),
this.clipboard = const ClipboardWrapper(),
@ -63,6 +64,7 @@ class RestoreWalletView extends ConsumerStatefulWidget {
final String walletName;
final Coin coin;
final String mnemonicPassphrase;
final int seedWordsLength;
final DateTime restoreFromDate;
@ -290,7 +292,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
// without using them
await manager.recoverFromMnemonic(
mnemonic: mnemonic,
mnemonicPassphrase: "", // TODO add ui for certain coins
mnemonicPassphrase: widget.mnemonicPassphrase,
maxUnusedAddressGap: widget.coin == Coin.firo ? 50 : 20,
maxNumberOfIndexesToCheck: 1000,
height: height,

View file

@ -26,16 +26,14 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
class ExchangeCurrencySelectionView extends StatefulWidget {
const ExchangeCurrencySelectionView({
Key? key,
required this.exchangeName,
required this.willChange,
required this.paired,
required this.willChangeTicker,
required this.pairedTicker,
required this.isFixedRate,
required this.willChangeIsSend,
}) : super(key: key);
final String exchangeName;
final Currency? willChange;
final Currency? paired;
final String? willChangeTicker;
final String? pairedTicker;
final bool isFixedRate;
final bool willChangeIsSend;
@ -89,7 +87,7 @@ class _ExchangeCurrencySelectionViewState
}
Future<List<Currency>> _loadCurrencies() async {
if (widget.paired == null) {
if (widget.pairedTicker == null) {
return await _getCurrencies();
}
@ -109,7 +107,6 @@ class _ExchangeCurrencySelectionViewState
Future<Currency?> _getCurrency(String ticker) {
return ExchangeDataLoadingService.instance.isar.currencies
.where()
.exchangeNameEqualTo(widget.exchangeName)
.filter()
.tickerEqualTo(ticker, caseSensitive: false)
.group((q) => widget.isFixedRate
@ -127,7 +124,6 @@ class _ExchangeCurrencySelectionViewState
Future<List<Pair>> _loadAvailablePairs() {
final query = ExchangeDataLoadingService.instance.isar.pairs
.where()
.exchangeNameEqualTo(widget.exchangeName)
.filter()
.group((q) => widget.isFixedRate
? q
@ -140,8 +136,8 @@ class _ExchangeCurrencySelectionViewState
.rateTypeEqualTo(SupportedRateType.estimated))
.and()
.group((q) => widget.willChangeIsSend
? q.toEqualTo(widget.paired!.ticker, caseSensitive: false)
: q.fromEqualTo(widget.paired!.ticker, caseSensitive: false));
? q.toEqualTo(widget.pairedTicker!, caseSensitive: false)
: q.fromEqualTo(widget.pairedTicker!, caseSensitive: false));
if (widget.willChangeIsSend) {
return query.sortByFrom().findAll();
@ -153,7 +149,6 @@ class _ExchangeCurrencySelectionViewState
Future<List<Currency>> _getCurrencies() async {
return ExchangeDataLoadingService.instance.isar.currencies
.where()
.exchangeNameEqualTo(widget.exchangeName)
.filter()
.group((q) => widget.isFixedRate
? q
@ -166,6 +161,7 @@ class _ExchangeCurrencySelectionViewState
.rateTypeEqualTo(SupportedRateType.estimated))
.sortByIsStackCoin()
.thenByName()
.distinctByTicker(caseSensitive: false)
.findAll();
}
@ -174,7 +170,7 @@ class _ExchangeCurrencySelectionViewState
return _currencies;
}
if (widget.paired == null) {
if (widget.pairedTicker == null) {
return _currencies
.where((e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
@ -183,7 +179,7 @@ class _ExchangeCurrencySelectionViewState
} else {
return _currencies
.where((e) =>
e.ticker.toLowerCase() != widget.paired!.ticker.toLowerCase() &&
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() &&
(e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase())))
.toList(growable: false);
@ -322,8 +318,7 @@ class _ExchangeCurrencySelectionViewState
Flexible(
child: Builder(builder: (context) {
final coins = Coin.values.where((e) =>
e.ticker.toLowerCase() !=
widget.paired?.ticker.toLowerCase());
e.ticker.toLowerCase() != widget.pairedTicker?.toLowerCase());
final items = filter(_searchString)
.where((e) => coins

View file

@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
@ -13,7 +14,6 @@ import 'package:stackwallet/pages/exchange_view/exchange_coin_selection/exchange
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_1_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_provider_options.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/rate_type_toggle.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
import 'package:stackwallet/providers/providers.dart';
@ -22,6 +22,7 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
@ -128,8 +129,37 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
});
}
Future<AggregateCurrency> _getAggregateCurrency(Currency currency) async {
final rateType = ref.read(exchangeFormStateProvider).exchangeRateType;
final currencies = await ExchangeDataLoadingService.instance.isar.currencies
.filter()
.group((q) => rateType == ExchangeRateType.fixed
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.and()
.tickerEqualTo(
currency.ticker,
caseSensitive: false,
)
.findAll();
final items = [Tuple2(currency.exchangeName, currency)];
for (final currency in currencies) {
items.add(Tuple2(currency.exchangeName, currency));
}
return AggregateCurrency(exchangeCurrencyPairs: items);
}
void selectSendCurrency() async {
final type = (ref.read(prefsChangeNotifierProvider).exchangeRateType);
final type = (ref.read(exchangeFormStateProvider).exchangeRateType);
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "";
if (walletInitiated &&
@ -139,17 +169,18 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
final selectedCurrency = await _showCurrencySelectionSheet(
willChange: ref.read(exchangeFormStateProvider).sendCurrency,
willChange: ref.read(exchangeFormStateProvider).sendCurrency?.ticker,
willChangeIsSend: true,
paired: ref.read(exchangeFormStateProvider).receiveCurrency,
paired: ref.read(exchangeFormStateProvider).receiveCurrency?.ticker,
isFixedRate: type == ExchangeRateType.fixed,
);
if (selectedCurrency != null) {
await showUpdatingExchangeRate(
whileFuture: ref
.read(exchangeFormStateProvider)
.updateSendCurrency(selectedCurrency, true),
whileFuture: _getAggregateCurrency(selectedCurrency).then(
(aggregateSelected) => ref
.read(exchangeFormStateProvider)
.updateSendCurrency(aggregateSelected, true)),
);
}
}
@ -163,18 +194,19 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
final selectedCurrency = await _showCurrencySelectionSheet(
willChange: ref.read(exchangeFormStateProvider).receiveCurrency,
willChange: ref.read(exchangeFormStateProvider).receiveCurrency?.ticker,
willChangeIsSend: false,
paired: ref.read(exchangeFormStateProvider).sendCurrency,
isFixedRate: ref.read(prefsChangeNotifierProvider).exchangeRateType ==
paired: ref.read(exchangeFormStateProvider).sendCurrency?.ticker,
isFixedRate: ref.read(exchangeFormStateProvider).exchangeRateType ==
ExchangeRateType.fixed,
);
if (selectedCurrency != null) {
await showUpdatingExchangeRate(
whileFuture: ref
.read(exchangeFormStateProvider)
.updateReceivingCurrency(selectedCurrency, true),
whileFuture: _getAggregateCurrency(selectedCurrency).then(
(aggregateSelected) => ref
.read(exchangeFormStateProvider)
.updateReceivingCurrency(aggregateSelected, true)),
);
}
}
@ -193,8 +225,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
Future<Currency?> _showCurrencySelectionSheet({
required Currency? willChange,
required Currency? paired,
required String? willChange,
required String? paired,
required bool isFixedRate,
required bool willChangeIsSend,
}) async {
@ -241,12 +273,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
.extension<StackColors>()!
.background,
child: ExchangeCurrencySelectionView(
exchangeName: ref
.read(currentExchangeNameStateProvider
.state)
.state,
willChange: willChange,
paired: paired,
willChangeTicker: willChange,
pairedTicker: paired,
isFixedRate: isFixedRate,
willChangeIsSend: willChangeIsSend,
),
@ -263,10 +291,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
: await Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (_) => ExchangeCurrencySelectionView(
exchangeName:
ref.read(currentExchangeNameStateProvider.state).state,
willChange: willChange,
paired: paired,
willChangeTicker: willChange,
pairedTicker: paired,
isFixedRate: isFixedRate,
willChangeIsSend: willChangeIsSend,
),
@ -298,68 +324,69 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
ref.read(exchangeFormStateProvider).reversed = false;
if (!(toTicker == "-" || fromTicker == "-")) {
final available = await ExchangeDataLoadingService.instance.isar.pairs
.where()
.exchangeNameEqualTo(
ref.read(currentExchangeNameStateProvider.state).state)
.filter()
.fromEqualTo(fromTicker)
.and()
.toEqualTo(toTicker)
.findAll();
// final available = await ExchangeDataLoadingService.instance.isar.pairs
// .where()
// .exchangeNameEqualTo(
// ref.read(currentExchangeNameStateProvider.state).state)
// .filter()
// .fromEqualTo(fromTicker)
// .and()
// .toEqualTo(toTicker)
// .findAll();
await ref.read(exchangeFormStateProvider).refresh();
if (available.isNotEmpty) {
final availableCurrencies = await ExchangeDataLoadingService
.instance.isar.currencies
.where()
.exchangeNameEqualTo(
ref.read(currentExchangeNameStateProvider.state).state)
.filter()
.tickerEqualTo(fromTicker)
.or()
.tickerEqualTo(toTicker)
.findAll();
if (availableCurrencies.length > 1) {
final from =
availableCurrencies.firstWhere((e) => e.ticker == fromTicker);
final to =
availableCurrencies.firstWhere((e) => e.ticker == toTicker);
final newFromAmount = Decimal.tryParse(_sendController.text);
ref.read(exchangeFormStateProvider).receiveAmount = newFromAmount;
if (newFromAmount == null) {
_receiveController.text = "";
}
await ref
.read(exchangeFormStateProvider)
.updateReceivingCurrency(to, false);
await ref
.read(exchangeFormStateProvider)
.updateSendCurrency(from, true);
_receiveController.text =
ref.read(exchangeFormStateProvider).toAmountString.isEmpty
? "-"
: ref.read(exchangeFormStateProvider).toAmountString;
if (mounted) {
Navigator.of(context, rootNavigator: isDesktop).pop();
}
return;
}
}
// if (available.isNotEmpty) {
// final availableCurrencies = await ExchangeDataLoadingService
// .instance.isar.currencies
// .where()
// .exchangeNameEqualTo(
// ref.read(currentExchangeNameStateProvider.state).state)
// .filter()
// .tickerEqualTo(fromTicker)
// .or()
// .tickerEqualTo(toTicker)
// .findAll();
//
// if (availableCurrencies.length > 1) {
// final from =
// availableCurrencies.firstWhere((e) => e.ticker == fromTicker);
// final to =
// availableCurrencies.firstWhere((e) => e.ticker == toTicker);
//
// final newFromAmount = Decimal.tryParse(_sendController.text);
// ref.read(exchangeFormStateProvider).receiveAmount = newFromAmount;
// if (newFromAmount == null) {
// _receiveController.text = "";
// }
//
// await ref
// .read(exchangeFormStateProvider)
// .updateReceivingCurrency(to, false);
// await ref
// .read(exchangeFormStateProvider)
// .updateSendCurrency(from, true);
//
// _receiveController.text =
// ref.read(exchangeFormStateProvider).toAmountString.isEmpty
// ? "-"
// : ref.read(exchangeFormStateProvider).toAmountString;
// if (mounted) {
// Navigator.of(context, rootNavigator: isDesktop).pop();
// }
// return;
// }
// }
}
}
void onExchangePressed() async {
final rateType = ref.read(prefsChangeNotifierProvider).exchangeRateType;
final rateType = ref.read(exchangeFormStateProvider).exchangeRateType;
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "";
final toTicker = ref.read(exchangeFormStateProvider).toTicker ?? "";
final sendAmount = ref.read(exchangeFormStateProvider).sendAmount!;
final estimate = ref.read(exchangeFormStateProvider).estimate!;
final exchangeName = ref.read(currentExchangeNameStateProvider.state).state;
final exchangeName = ref.read(exchangeFormStateProvider).exchange.name;
String rate;
@ -531,6 +558,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
rateType: rateType,
rateId: estimate.rateId,
reversed: estimate.reversed,
walletInitiated: walletInitiated,
);
if (mounted) {
@ -644,7 +672,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
debugPrint("BUILD: $runtimeType");
final rateType = ref.watch(
prefsChangeNotifierProvider.select((value) => value.exchangeRateType));
exchangeFormStateProvider.select((value) => value.exchangeRateType));
final isEstimated = rateType == ExchangeRateType.estimated;
@ -708,10 +736,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
onChanged: sendFieldOnChanged,
onButtonTap: selectSendCurrency,
isWalletCoin: isWalletCoin(coin, true),
image: ref.watch(exchangeFormStateProvider
.select((value) => value.sendCurrency?.image)),
ticker: ref.watch(
exchangeFormStateProvider.select((value) => value.fromTicker)),
currency: ref.watch(
exchangeFormStateProvider.select((value) => value.sendCurrency)),
),
SizedBox(
height: isDesktop ? 10 : 4,
@ -791,7 +817,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
background:
Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
onTap: () {
if (!(ref.read(prefsChangeNotifierProvider).exchangeRateType ==
if (!(ref.read(exchangeFormStateProvider).exchangeRateType ==
ExchangeRateType.estimated) &&
_receiveController.text == "-") {
_receiveController.text = "";
@ -800,13 +826,11 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
onChanged: receiveFieldOnChanged,
onButtonTap: selectReceiveCurrency,
isWalletCoin: isWalletCoin(coin, true),
image: ref.watch(exchangeFormStateProvider
.select((value) => value.receiveCurrency?.image)) ??
"",
ticker: ref.watch(
exchangeFormStateProvider.select((value) => value.toTicker)),
currency: ref.watch(exchangeFormStateProvider
.select((value) => value.receiveCurrency)),
readOnly: (rateType) == ExchangeRateType.estimated &&
ref.watch(exchangeProvider).name ==
ref.watch(exchangeFormStateProvider
.select((value) => value.exchange.name)) ==
ChangeNowExchange.exchangeName,
),
if (ref
@ -840,10 +864,6 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
if (ref.watch(exchangeFormStateProvider).sendAmount != null &&
ref.watch(exchangeFormStateProvider).sendAmount != Decimal.zero)
ExchangeProviderOptions(
from: ref.watch(exchangeFormStateProvider).fromTicker,
to: ref.watch(exchangeFormStateProvider).toTicker,
fromAmount: ref.watch(exchangeFormStateProvider).sendAmount,
toAmount: ref.watch(exchangeFormStateProvider).receiveAmount,
fixedRate: rateType == ExchangeRateType.fixed,
reversed: ref.watch(
exchangeFormStateProvider.select((value) => value.reversed)),

View file

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';

View file

@ -124,9 +124,9 @@ class _Step2ViewState extends ConsumerState<Step2View> {
@override
Widget build(BuildContext context) {
final supportsRefund =
ref.watch(currentExchangeNameStateProvider.state).state !=
MajesticBankExchange.exchangeName;
final supportsRefund = ref.watch(
exchangeFormStateProvider.select((value) => value.exchange.name)) !=
MajesticBankExchange.exchangeName;
return Background(
child: Scaffold(

View file

@ -5,16 +5,15 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_4_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/providers/exchange/current_exchange_name_state_provider.dart';
import 'package:stackwallet/providers/exchange/exchange_provider.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/exchange/exchange_response.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/services/notifications_api.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
@ -53,9 +52,9 @@ class _Step3ViewState extends ConsumerState<Step3View> {
@override
Widget build(BuildContext context) {
final supportsRefund =
ref.watch(currentExchangeNameStateProvider.state).state !=
MajesticBankExchange.exchangeName;
final supportsRefund = ref.watch(
exchangeFormStateProvider.select((value) => value.exchange.name)) !=
MajesticBankExchange.exchangeName;
return Background(
child: Scaffold(
@ -255,7 +254,8 @@ class _Step3ViewState extends ConsumerState<Step3View> {
final ExchangeResponse<Trade> response =
await ref
.read(exchangeProvider)
.read(exchangeFormStateProvider)
.exchange
.createTrade(
from: model.sendTicker,
to: model.receiveTicker,

File diff suppressed because it is too large Load diff

View file

@ -8,9 +8,12 @@ import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/trade_card.dart';
import 'package:tuple/tuple.dart';
@ -24,8 +27,38 @@ class ExchangeView extends ConsumerStatefulWidget {
}
class _ExchangeViewState extends ConsumerState<ExchangeView> {
bool _initialCachePopulationUnderway = false;
@override
void initState() {
if (!ref.read(prefsChangeNotifierProvider).externalCalls) {
if (ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
ExchangeDataLoadingService.instance
.init()
.then((_) => ExchangeDataLoadingService.instance.loadAll());
} else if (ExchangeDataLoadingService.instance.isLoading &&
ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
super.initState();
}
@ -38,154 +71,176 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return SafeArea(
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: const SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
top: 16,
),
child: ExchangeForm(),
),
return ConditionalParent(
condition: _initialCachePopulationUnderway,
builder: (child) {
return Stack(
children: [
child,
Material(
color: Theme.of(context)
.extension<StackColors>()!
.overlay
.withOpacity(0.6),
child: const CustomLoadingOverlay(
message: "Updating exchange data",
subMessage: "This could take a few minutes",
eventBus: null,
),
)
];
},
body: Builder(
builder: (buildContext) {
final trades = ref
.watch(tradesServiceProvider.select((value) => value.trades));
final tradeCount = trades.length;
final hasHistory = tradeCount > 0;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: CustomScrollView(
slivers: [
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
buildContext,
],
);
},
child: SafeArea(
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: const SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
top: 16,
),
child: ExchangeForm(),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 12,
),
Text(
"Trades",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
const SizedBox(
height: 12,
),
],
),
)
];
},
body: Builder(
builder: (buildContext) {
final trades = ref
.watch(tradesServiceProvider.select((value) => value.trades));
final tradeCount = trades.length;
final hasHistory = tradeCount > 0;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: CustomScrollView(
slivers: [
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
buildContext,
),
),
),
if (hasHistory)
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Padding(
padding: const EdgeInsets.all(4),
child: TradeCard(
key: Key("tradeCard_${trades[index].uuid}"),
trade: trades[index],
onTap: () async {
final String tradeId = trades[index].tradeId;
final lookup = ref
.read(tradeSentFromStackLookupProvider)
.all;
//todo: check if print needed
// debugPrint("ALL: $lookup");
final String? txid = ref
.read(tradeSentFromStackLookupProvider)
.getTxidForTradeId(tradeId);
final List<String>? walletIds = ref
.read(tradeSentFromStackLookupProvider)
.getWalletIdsForTradeId(tradeId);
if (txid != null &&
walletIds != null &&
walletIds.isNotEmpty) {
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(walletIds.first);
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
if (mounted) {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(tradeId, tx,
walletIds.first, manager.walletName),
));
}
} else {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(
tradeId, null, walletIds?.first, null),
));
}
},
),
);
}, childCount: tradeCount),
),
if (!hasHistory)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 12,
),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
"Trades will appear here",
textAlign: TextAlign.center,
style: STextStyles.itemSubtitle(context),
Text(
"Trades",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
const SizedBox(
height: 12,
),
],
),
),
),
if (hasHistory)
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Padding(
padding: const EdgeInsets.all(4),
child: TradeCard(
key: Key("tradeCard_${trades[index].uuid}"),
trade: trades[index],
onTap: () async {
final String tradeId = trades[index].tradeId;
final lookup = ref
.read(tradeSentFromStackLookupProvider)
.all;
//todo: check if print needed
// debugPrint("ALL: $lookup");
final String? txid = ref
.read(tradeSentFromStackLookupProvider)
.getTxidForTradeId(tradeId);
final List<String>? walletIds = ref
.read(tradeSentFromStackLookupProvider)
.getWalletIdsForTradeId(tradeId);
if (txid != null &&
walletIds != null &&
walletIds.isNotEmpty) {
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(walletIds.first);
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
if (mounted) {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(tradeId, tx,
walletIds.first, manager.walletName),
));
}
} else {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(
tradeId, null, walletIds?.first, null),
));
}
},
),
);
}, childCount: tradeCount),
),
if (!hasHistory)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
"Trades will appear here",
textAlign: TextAlign.center,
style: STextStyles.itemSubtitle(context),
),
),
),
),
),
),
],
),
);
},
],
),
);
},
),
),
),
);

View file

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/exceptions/exchange/pair_unavailable_exception.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
@ -20,27 +21,62 @@ import 'package:stackwallet/widgets/animated_text.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class ExchangeProviderOptions extends ConsumerWidget {
class ExchangeProviderOptions extends ConsumerStatefulWidget {
const ExchangeProviderOptions({
Key? key,
required this.from,
required this.to,
required this.fromAmount,
required this.toAmount,
required this.fixedRate,
required this.reversed,
}) : super(key: key);
final String? from;
final String? to;
final Decimal? fromAmount;
final Decimal? toAmount;
final bool fixedRate;
final bool reversed;
@override
Widget build(BuildContext context, WidgetRef ref) {
final isDesktop = Util.isDesktop;
ConsumerState<ExchangeProviderOptions> createState() =>
_ExchangeProviderOptionsState();
}
class _ExchangeProviderOptionsState
extends ConsumerState<ExchangeProviderOptions> {
final isDesktop = Util.isDesktop;
bool exchangeSupported({
required String exchangeName,
required AggregateCurrency? sendCurrency,
required AggregateCurrency? receiveCurrency,
}) {
final send = sendCurrency?.forExchange(exchangeName);
if (send == null) return false;
final rcv = receiveCurrency?.forExchange(exchangeName);
if (rcv == null) return false;
if (widget.fixedRate) {
return send.supportsFixedRate && rcv.supportsFixedRate;
} else {
return send.supportsEstimatedRate && rcv.supportsEstimatedRate;
}
}
@override
Widget build(BuildContext context) {
final sendCurrency = ref.watch(exchangeFormStateProvider).sendCurrency;
final receivingCurrency =
ref.watch(exchangeFormStateProvider).receiveCurrency;
final fromAmount = ref.watch(exchangeFormStateProvider).sendAmount;
final toAmount = ref.watch(exchangeFormStateProvider).receiveAmount;
final showChangeNow = exchangeSupported(
exchangeName: ChangeNowExchange.exchangeName,
sendCurrency: sendCurrency,
receiveCurrency: receivingCurrency,
);
final showMajesticBank = exchangeSupported(
exchangeName: MajesticBankExchange.exchangeName,
sendCurrency: sendCurrency,
receiveCurrency: receivingCurrency,
);
return RoundedWhiteContainer(
padding: isDesktop ? const EdgeInsets.all(0) : const EdgeInsets.all(12),
borderColor: isDesktop
@ -48,181 +84,196 @@ class ExchangeProviderOptions extends ConsumerWidget {
: null,
child: Column(
children: [
ConditionalParent(
condition: isDesktop,
builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
child: GestureDetector(
onTap: () {
if (ref.read(currentExchangeNameStateProvider.state).state !=
ChangeNowExchange.exchangeName) {
ref.read(currentExchangeNameStateProvider.state).state =
ChangeNowExchange.exchangeName;
ref.read(exchangeFormStateProvider).updateExchange(
exchange: ref.read(exchangeProvider),
shouldUpdateData: true,
shouldNotifyListeners: true,
);
}
},
child: Container(
color: Colors.transparent,
child: Padding(
padding: isDesktop
? const EdgeInsets.all(16)
: const EdgeInsets.all(0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Padding(
padding:
EdgeInsets.only(top: isDesktop ? 20.0 : 15.0),
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: ChangeNowExchange.exchangeName,
groupValue: ref
.watch(currentExchangeNameStateProvider.state)
.state,
onChanged: (_) {
// if (value is String) {
// ref
// .read(
// currentExchangeNameStateProvider.state)
// .state = value;
// ref
// .read(exchangeFormStateProvider(ref
// .read(prefsChangeNotifierProvider)
// .exchangeRateType))
// .exchange =
// Exchange.fromName(ref
// .read(currentExchangeNameStateProvider
// .state)
// .state);
// }
},
if (showChangeNow)
ConditionalParent(
condition: isDesktop,
builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
child: GestureDetector(
onTap: () {
if (ref.read(exchangeFormStateProvider).exchange.name !=
ChangeNowExchange.exchangeName) {
ref.read(exchangeFormStateProvider).updateExchange(
exchange: ChangeNowExchange.instance,
shouldUpdateData: true,
shouldNotifyListeners: true,
);
}
},
child: Container(
color: Colors.transparent,
child: Padding(
padding: isDesktop
? const EdgeInsets.all(16)
: const EdgeInsets.all(0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Padding(
padding:
EdgeInsets.only(top: isDesktop ? 20.0 : 15.0),
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: ChangeNowExchange.exchangeName,
groupValue: ref.watch(exchangeFormStateProvider
.select((value) => value.exchange.name)),
onChanged: (_) {
if (ref
.read(exchangeFormStateProvider)
.exchange
.name !=
ChangeNowExchange.exchangeName) {
ref
.read(exchangeFormStateProvider)
.updateExchange(
exchange: ChangeNowExchange.instance,
shouldUpdateData: true,
shouldNotifyListeners: true,
);
}
},
),
),
),
),
const SizedBox(
width: 14,
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: SizedBox(
width: isDesktop ? 32 : 24,
height: isDesktop ? 32 : 24,
child: SvgPicture.asset(
Assets.exchange.changeNow,
const SizedBox(
width: 14,
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: SizedBox(
width: isDesktop ? 32 : 24,
height: isDesktop ? 32 : 24,
child: SvgPicture.asset(
Assets.exchange.changeNow,
width: isDesktop ? 32 : 24,
height: isDesktop ? 32 : 24,
),
),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ChangeNowExchange.exchangeName,
style: STextStyles.titleBold12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark2,
),
),
if (from != null &&
to != null &&
toAmount != null &&
toAmount! > Decimal.zero &&
fromAmount != null &&
fromAmount! > Decimal.zero)
FutureBuilder(
future: ChangeNowExchange.instance.getEstimate(
from!,
to!,
reversed ? toAmount! : fromAmount!,
fixedRate,
reversed,
const SizedBox(
width: 10,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ChangeNowExchange.exchangeName,
style:
STextStyles.titleBold12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark2,
),
builder: (context,
AsyncSnapshot<ExchangeResponse<Estimate>>
snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
final estimate = snapshot.data?.value;
if (estimate != null) {
Decimal rate;
if (estimate.reversed) {
rate = (toAmount! /
estimate.estimatedAmount)
.toDecimal(
scaleOnInfinitePrecision: 12);
} else {
rate = (estimate.estimatedAmount /
fromAmount!)
.toDecimal(
scaleOnInfinitePrecision: 12);
}
Coin coin;
try {
coin =
coinFromTickerCaseInsensitive(to!);
} catch (_) {
coin = Coin.bitcoin;
}
),
if (sendCurrency != null &&
receivingCurrency != null &&
toAmount != null &&
toAmount > Decimal.zero &&
fromAmount != null &&
fromAmount > Decimal.zero)
FutureBuilder(
future:
ChangeNowExchange.instance.getEstimate(
sendCurrency.ticker,
receivingCurrency.ticker,
widget.reversed ? toAmount : fromAmount,
widget.fixedRate,
widget.reversed,
),
builder: (context,
AsyncSnapshot<ExchangeResponse<Estimate>>
snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
final estimate = snapshot.data?.value;
if (estimate != null) {
Decimal rate;
if (estimate.reversed) {
rate = (toAmount /
estimate.estimatedAmount)
.toDecimal(
scaleOnInfinitePrecision: 12);
} else {
rate = (estimate.estimatedAmount /
fromAmount)
.toDecimal(
scaleOnInfinitePrecision: 12);
}
Coin coin;
try {
coin = coinFromTickerCaseInsensitive(
receivingCurrency.ticker);
} catch (_) {
coin = Coin.bitcoin;
}
return Text(
"1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
value: rate,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select(
(value) => value.locale),
return Text(
"1 ${sendCurrency.ticker.toUpperCase()} ~ ${Format.localizedStringAsFixed(
value: rate,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select(
(value) => value.locale),
),
decimalPlaces:
Constants.decimalPlacesForCoin(
coin),
)} ${receivingCurrency.ticker.toUpperCase()}",
style: STextStyles.itemSubtitle12(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
decimalPlaces:
Constants.decimalPlacesForCoin(
coin),
)} ${to!.toUpperCase()}",
style:
STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
} else if (snapshot.data?.exception
is PairUnavailableException) {
return Text(
"Unsupported pair",
style:
STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
);
} else if (snapshot.data?.exception
is PairUnavailableException) {
return Text(
"Unsupported pair",
style: STextStyles.itemSubtitle12(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
} else {
Logging.instance.log(
"$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}",
level: LogLevel.Warning,
);
return Text(
"Failed to fetch rate",
style: STextStyles.itemSubtitle12(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
}
} else {
Logging.instance.log(
"$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}",
level: LogLevel.Warning,
);
return Text(
"Failed to fetch rate",
return AnimatedText(
stringsToLoopThrough: const [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
style:
STextStyles.itemSubtitle12(context)
.copyWith(
@ -232,233 +283,234 @@ class ExchangeProviderOptions extends ConsumerWidget {
),
);
}
} else {
return AnimatedText(
stringsToLoopThrough: const [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
}
},
),
if (!(from != null &&
to != null &&
toAmount != null &&
toAmount! > Decimal.zero &&
fromAmount != null &&
fromAmount! > Decimal.zero))
Text(
"n/a",
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
},
),
),
],
if (!(sendCurrency != null &&
receivingCurrency != null &&
toAmount != null &&
toAmount > Decimal.zero &&
fromAmount != null &&
fromAmount > Decimal.zero))
Text(
"n/a",
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
),
],
),
),
),
],
],
),
),
),
),
),
),
if (isDesktop)
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
if (!isDesktop)
const SizedBox(
height: 16,
),
ConditionalParent(
condition: isDesktop,
builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
child: GestureDetector(
onTap: () {
if (ref.read(currentExchangeNameStateProvider.state).state !=
MajesticBankExchange.exchangeName) {
ref.read(currentExchangeNameStateProvider.state).state =
MajesticBankExchange.exchangeName;
ref.read(exchangeFormStateProvider).updateExchange(
exchange: ref.read(exchangeProvider),
shouldUpdateData: true,
shouldNotifyListeners: true,
);
}
},
child: Container(
color: Colors.transparent,
child: Padding(
padding: isDesktop
? const EdgeInsets.all(16)
: const EdgeInsets.all(0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Padding(
padding:
EdgeInsets.only(top: isDesktop ? 20.0 : 15.0),
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: MajesticBankExchange.exchangeName,
groupValue: ref
.watch(currentExchangeNameStateProvider.state)
.state,
onChanged: (_) {
// if (value is String) {
// ref
// .read(
// currentExchangeNameStateProvider.state)
// .state = value;
// ref
// .read(exchangeFormStateProvider(ref
// .read(prefsChangeNotifierProvider)
// .exchangeRateType))
// .exchange =
// Exchange.fromName(ref
// .read(currentExchangeNameStateProvider
// .state)
// .state);
// }
},
if (showChangeNow && showMajesticBank)
isDesktop
? Container(
height: 1,
color:
Theme.of(context).extension<StackColors>()!.background,
)
: const SizedBox(
height: 16,
),
if (showMajesticBank)
ConditionalParent(
condition: isDesktop,
builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
child: GestureDetector(
onTap: () {
if (ref.read(exchangeFormStateProvider).exchange.name !=
MajesticBankExchange.exchangeName) {
ref.read(exchangeFormStateProvider).updateExchange(
exchange: MajesticBankExchange.instance,
shouldUpdateData: true,
shouldNotifyListeners: true,
);
}
},
child: Container(
color: Colors.transparent,
child: Padding(
padding: isDesktop
? const EdgeInsets.all(16)
: const EdgeInsets.all(0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Padding(
padding:
EdgeInsets.only(top: isDesktop ? 20.0 : 15.0),
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: MajesticBankExchange.exchangeName,
groupValue: ref.watch(exchangeFormStateProvider
.select((value) => value.exchange.name)),
onChanged: (_) {
if (ref
.read(exchangeFormStateProvider)
.exchange
.name !=
MajesticBankExchange.exchangeName) {
ref
.read(exchangeFormStateProvider)
.updateExchange(
exchange: MajesticBankExchange.instance,
shouldUpdateData: true,
shouldNotifyListeners: true,
);
}
},
),
),
),
),
const SizedBox(
width: 14,
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: SizedBox(
width: isDesktop ? 32 : 24,
height: isDesktop ? 32 : 24,
child: SvgPicture.asset(
Assets.exchange.majesticBankBlue,
const SizedBox(
width: 14,
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: SizedBox(
width: isDesktop ? 32 : 24,
height: isDesktop ? 32 : 24,
child: SvgPicture.asset(
Assets.exchange.majesticBankBlue,
width: isDesktop ? 32 : 24,
height: isDesktop ? 32 : 24,
),
),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
MajesticBankExchange.exchangeName,
style: STextStyles.titleBold12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark2,
),
),
if (from != null &&
to != null &&
toAmount != null &&
toAmount! > Decimal.zero &&
fromAmount != null &&
fromAmount! > Decimal.zero)
FutureBuilder(
future:
MajesticBankExchange.instance.getEstimate(
from!,
to!,
reversed ? toAmount! : fromAmount!,
fixedRate,
reversed,
const SizedBox(
width: 10,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
MajesticBankExchange.exchangeName,
style:
STextStyles.titleBold12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark2,
),
builder: (context,
AsyncSnapshot<ExchangeResponse<Estimate>>
snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
final estimate = snapshot.data?.value;
if (estimate != null) {
Decimal rate;
if (estimate.reversed) {
rate = (toAmount! /
estimate.estimatedAmount)
.toDecimal(
scaleOnInfinitePrecision: 12);
} else {
rate = (estimate.estimatedAmount /
fromAmount!)
.toDecimal(
scaleOnInfinitePrecision: 12);
}
Coin coin;
try {
coin =
coinFromTickerCaseInsensitive(to!);
} catch (_) {
coin = Coin.bitcoin;
}
),
if (sendCurrency != null &&
receivingCurrency != null &&
toAmount != null &&
toAmount > Decimal.zero &&
fromAmount != null &&
fromAmount > Decimal.zero)
FutureBuilder(
future:
MajesticBankExchange.instance.getEstimate(
sendCurrency.ticker,
receivingCurrency.ticker,
widget.reversed ? toAmount : fromAmount,
widget.fixedRate,
widget.reversed,
),
builder: (context,
AsyncSnapshot<ExchangeResponse<Estimate>>
snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
final estimate = snapshot.data?.value;
if (estimate != null) {
Decimal rate;
if (estimate.reversed) {
rate = (toAmount /
estimate.estimatedAmount)
.toDecimal(
scaleOnInfinitePrecision: 12);
} else {
rate = (estimate.estimatedAmount /
fromAmount)
.toDecimal(
scaleOnInfinitePrecision: 12);
}
Coin coin;
try {
coin = coinFromTickerCaseInsensitive(
receivingCurrency.ticker);
} catch (_) {
coin = Coin.bitcoin;
}
return Text(
"1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
value: rate,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select(
(value) => value.locale),
return Text(
"1 ${sendCurrency.ticker.toUpperCase()} ~ ${Format.localizedStringAsFixed(
value: rate,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select(
(value) => value.locale),
),
decimalPlaces:
Constants.decimalPlacesForCoin(
coin),
)} ${receivingCurrency.ticker.toUpperCase()}",
style: STextStyles.itemSubtitle12(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
decimalPlaces:
Constants.decimalPlacesForCoin(
coin),
)} ${to!.toUpperCase()}",
style:
STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
} else if (snapshot.data?.exception
is PairUnavailableException) {
return Text(
"Unsupported pair",
style:
STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
);
} else if (snapshot.data?.exception
is PairUnavailableException) {
return Text(
"Unsupported pair",
style: STextStyles.itemSubtitle12(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
} else {
Logging.instance.log(
"$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}",
level: LogLevel.Warning,
);
return Text(
"Failed to fetch rate",
style: STextStyles.itemSubtitle12(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
}
} else {
Logging.instance.log(
"$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}",
level: LogLevel.Warning,
);
return Text(
"Failed to fetch rate",
return AnimatedText(
stringsToLoopThrough: const [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
style:
STextStyles.itemSubtitle12(context)
.copyWith(
@ -468,53 +520,37 @@ class ExchangeProviderOptions extends ConsumerWidget {
),
);
}
} else {
return AnimatedText(
stringsToLoopThrough: const [
"Loading",
"Loading.",
"Loading..",
"Loading...",
],
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
);
}
},
),
if (!(from != null &&
to != null &&
toAmount != null &&
toAmount! > Decimal.zero &&
fromAmount != null &&
fromAmount! > Decimal.zero))
Text(
"n/a",
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
},
),
),
],
if (!(sendCurrency != null &&
receivingCurrency != null &&
toAmount != null &&
toAmount > Decimal.zero &&
fromAmount != null &&
fromAmount > Decimal.zero))
Text(
"n/a",
style: STextStyles.itemSubtitle12(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
),
],
),
),
),
],
],
),
),
),
),
),
),
if (isDesktop)
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
// if (isDesktop)
// Container(
// height: 1,
// color: Theme.of(context).extension<StackColors>()!.background,
// ),
// if (!isDesktop)
// const SizedBox(
// height: 16,

View file

@ -1,210 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
enum ExchangeRateType { estimated, fixed }
class ExchangeRateSheet extends ConsumerWidget {
const ExchangeRateSheet({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(20),
),
),
child: Padding(
padding: const EdgeInsets.only(
left: 24,
right: 24,
top: 10,
bottom: 0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
decoration: BoxDecoration(
color:
Theme.of(context).extension<StackColors>()!.textSubtitle4,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
width: 60,
height: 4,
),
),
const SizedBox(
height: 36,
),
Text(
"Exchange rate",
style: STextStyles.pageTitleH2(context),
textAlign: TextAlign.left,
),
const SizedBox(
height: 16,
),
GestureDetector(
onTap: () {
final state =
ref.read(prefsChangeNotifierProvider).exchangeRateType;
if (state != ExchangeRateType.estimated) {
ref.read(prefsChangeNotifierProvider).exchangeRateType =
ExchangeRateType.estimated;
}
Navigator.of(context).pop(ExchangeRateType.estimated);
},
child: Container(
color: Colors.transparent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
SizedBox(
width: 20,
height: 20,
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: ExchangeRateType.estimated,
groupValue: ref.watch(prefsChangeNotifierProvider
.select((value) => value.exchangeRateType)),
onChanged: (x) {
//todo: check if print needed
// debugPrint(x.toString());
ref
.read(prefsChangeNotifierProvider)
.exchangeRateType =
ExchangeRateType.estimated;
Navigator.of(context)
.pop(ExchangeRateType.estimated);
},
),
)
],
),
const SizedBox(
width: 12,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Estimated rate",
style: STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
const SizedBox(
height: 2,
),
Text(
"ChangeNOW will pick the best rate for you during the moment of the exchange.",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
textAlign: TextAlign.left,
),
],
),
)
],
),
),
),
const SizedBox(
height: 16,
),
GestureDetector(
onTap: () {
final state =
ref.read(prefsChangeNotifierProvider).exchangeRateType;
if (state != ExchangeRateType.fixed) {
ref.read(prefsChangeNotifierProvider).exchangeRateType =
ExchangeRateType.fixed;
}
Navigator.of(context).pop(ExchangeRateType.fixed);
},
child: Container(
color: Colors.transparent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
SizedBox(
width: 20,
height: 20,
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: ExchangeRateType.fixed,
groupValue: ref.watch(prefsChangeNotifierProvider
.select((value) => value.exchangeRateType)),
onChanged: (x) {
ref
.read(prefsChangeNotifierProvider)
.exchangeRateType = ExchangeRateType.fixed;
Navigator.of(context).pop(ExchangeRateType.fixed);
},
),
),
],
),
const SizedBox(
width: 12,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Fixed rate",
style: STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
const SizedBox(
height: 2,
),
Text(
"You will get the exact exchange amount displayed - ChangeNOW takes all the rate risks.",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
textAlign: TextAlign.left,
)
],
),
),
],
),
),
),
const SizedBox(
height: 24,
),
],
),
),
);
}
}

View file

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/toggle.dart';
@ -24,16 +24,12 @@ class RateTypeToggle extends ConsumerWidget {
return Toggle(
onValueChanged: (value) {
if (value) {
ref.read(prefsChangeNotifierProvider).exchangeRateType =
ExchangeRateType.fixed;
onChanged?.call(ExchangeRateType.fixed);
} else {
ref.read(prefsChangeNotifierProvider).exchangeRateType =
ExchangeRateType.estimated;
onChanged?.call(ExchangeRateType.estimated);
}
},
isOn: ref.watch(prefsChangeNotifierProvider
isOn: ref.watch(exchangeFormStateProvider
.select((value) => value.exchangeRateType)) ==
ExchangeRateType.fixed,
onColor: isDesktop

View file

@ -18,6 +18,7 @@ import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
@ -1128,6 +1129,10 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
url =
"https://simpleswap.io/exchange?id=${trade.tradeId}";
break;
case MajesticBankExchange.exchangeName:
url =
"https://majesticbank.sc/track?trx=${trade.tradeId}";
break;
}
return ConditionalParent(
condition: isDesktop,

View file

@ -4,11 +4,15 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
class WalletInitiatedExchangeView extends ConsumerStatefulWidget {
const WalletInitiatedExchangeView({
@ -32,10 +36,41 @@ class _WalletInitiatedExchangeViewState
late final String walletId;
late final Coin coin;
bool _initialCachePopulationUnderway = false;
@override
void initState() {
walletId = widget.walletId;
coin = widget.coin;
if (!ref.read(prefsChangeNotifierProvider).externalCalls) {
if (ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
ExchangeDataLoadingService.instance
.init()
.then((_) => ExchangeDataLoadingService.instance.loadAll());
} else if (ExchangeDataLoadingService.instance.isLoading &&
ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
super.initState();
}
@ -48,76 +83,98 @@ class _WalletInitiatedExchangeViewState
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
return ConditionalParent(
condition: _initialCachePopulationUnderway,
builder: (child) {
return Stack(
children: [
child,
Material(
color: Theme.of(context)
.extension<StackColors>()!
.overlay
.withOpacity(0.6),
child: const CustomLoadingOverlay(
message: "Updating exchange data",
subMessage: "This could take a few minutes",
eventBus: null,
),
)
],
);
},
child: Background(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
title: Text(
"Exchange",
style: STextStyles.navBarTitle(context),
),
),
title: Text(
"Exchange",
style: STextStyles.navBarTitle(context),
),
),
body: LayoutBuilder(
builder: (context, constraints) {
final width = MediaQuery.of(context).size.width - 32;
return Padding(
padding: const EdgeInsets.all(12),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
StepRow(
count: 4,
current: 0,
width: width,
),
const SizedBox(
height: 14,
),
Text(
"Exchange amount",
style: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 8,
),
Text(
"Network fees and other exchange charges are included in the rate.",
style: STextStyles.itemSubtitle(context),
),
const SizedBox(
height: 24,
),
ExchangeForm(
walletId: walletId,
coin: coin,
),
],
body: LayoutBuilder(
builder: (context, constraints) {
final width = MediaQuery.of(context).size.width - 32;
return Padding(
padding: const EdgeInsets.all(12),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
StepRow(
count: 4,
current: 0,
width: width,
),
const SizedBox(
height: 14,
),
Text(
"Exchange amount",
style: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 8,
),
Text(
"Network fees and other exchange charges are included in the rate.",
style: STextStyles.itemSubtitle(context),
),
const SizedBox(
height: 24,
),
ExchangeForm(
walletId: walletId,
coin: coin,
),
],
),
),
),
),
),
),
);
},
);
},
),
),
),
);

View file

@ -13,7 +13,6 @@ import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/stack_restoring_ui_state.dart';
import 'package:stackwallet/models/trade_wallet_lookup.dart';
import 'package:stackwallet/models/wallet_restore_state.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
@ -246,7 +245,6 @@ abstract class SWB {
final _prefs = Prefs.instance;
await _prefs.init();
prefs['currency'] = _prefs.currency;
prefs['exchangeRateType'] = _prefs.exchangeRateType.name;
prefs['useBiometrics'] = _prefs.useBiometrics;
prefs['hasPin'] = _prefs.hasPin;
prefs['language'] = _prefs.language;
@ -992,9 +990,6 @@ abstract class SWB {
final _prefs = Prefs.instance;
await _prefs.init();
_prefs.currency = prefs['currency'] as String;
_prefs.exchangeRateType = prefs['exchangeRateType'] == "estimated"
? ExchangeRateType.estimated
: ExchangeRateType.fixed;
// _prefs.useBiometrics = prefs['useBiometrics'] as bool;
// _prefs.hasPin = prefs['hasPin'] as bool;
_prefs.language = prefs['language'] as String;

View file

@ -29,7 +29,6 @@ import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
@ -38,6 +37,7 @@ import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
@ -77,6 +77,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
late StreamSubscription<dynamic> _syncStatusSubscription;
late StreamSubscription<dynamic> _nodeStatusSubscription;
bool _rescanningOnOpen = false;
@override
void initState() {
walletId = widget.walletId;
@ -91,7 +93,18 @@ class _WalletViewState extends ConsumerState<WalletView> {
_shouldDisableAutoSyncOnLogOut = false;
}
ref.read(managerProvider).refresh();
if (ref.read(managerProvider).rescanOnOpenVersion == Constants.rescanV1) {
_rescanningOnOpen = true;
ref.read(managerProvider).fullRescan(20, 1000).then(
(_) => ref.read(managerProvider).resetRescanOnOpen().then(
(_) => WidgetsBinding.instance.addPostFrameCallback(
(_) => setState(() => _rescanningOnOpen = false),
),
),
);
} else {
ref.read(managerProvider).refresh();
}
if (ref.read(managerProvider).isRefreshing) {
_currentSyncStatus = WalletSyncStatus.syncing;
@ -278,10 +291,9 @@ class _WalletViewState extends ConsumerState<WalletView> {
unawaited(
Navigator.of(context).pushNamed(
WalletInitiatedExchangeView.routeName,
arguments: Tuple3(
arguments: Tuple2(
walletId,
coin,
_loadCNData,
),
),
);
@ -355,435 +367,454 @@ class _WalletViewState extends ConsumerState<WalletView> {
}
}
void _loadCNData() {
// unawaited future
// if (ref.read(prefsChangeNotifierProvider).externalCalls) {
ExchangeDataLoadingService.instance.loadAll();
// .loadAll(ref, coin: ref.read(managerProvider).coin);
// } else {
// Logging.instance.log("User does not want to use external calls",
// level: LogLevel.Info);
// }
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final coin = ref.watch(managerProvider.select((value) => value.coin));
return WillPopScope(
onWillPop: _onWillPop,
child: Background(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () {
_logout();
Navigator.of(context).pop();
},
),
titleSpacing: 0,
title: Row(
children: [
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
width: 24,
height: 24,
return ConditionalParent(
condition: _rescanningOnOpen,
builder: (child) {
return WillPopScope(
onWillPop: () async => !_rescanningOnOpen,
child: Stack(
children: [
child,
Background(
child: CustomLoadingOverlay(
message:
"Migration in progress\nThis could take a while\nPlease don't leave this screen",
subMessage: "This only needs to run once per wallet",
eventBus: null,
textColor:
Theme.of(context).extension<StackColors>()!.textDark,
),
const SizedBox(
width: 16,
),
Expanded(
child: Text(
ref.watch(
managerProvider.select((value) => value.walletName)),
style: STextStyles.navBarTitle(context),
overflow: TextOverflow.ellipsis,
),
)
],
),
actions: [
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("walletViewRadioButton"),
size: 36,
shadows: const [],
color:
Theme.of(context).extension<StackColors>()!.background,
icon: _buildNetworkIcon(_currentSyncStatus),
onPressed: () {
Navigator.of(context).pushNamed(
WalletNetworkSettingsView.routeName,
arguments: Tuple3(
walletId,
_currentSyncStatus,
_currentNodeStatus,
),
);
},
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("walletViewAlertsButton"),
size: 36,
shadows: const [],
color:
Theme.of(context).extension<StackColors>()!.background,
icon: SvgPicture.asset(
ref.watch(notificationsProvider.select((value) =>
value.hasUnreadNotificationsFor(walletId)))
? Assets.svg.bellNew(context)
: Assets.svg.bell,
width: 20,
height: 20,
color: ref.watch(notificationsProvider.select((value) =>
value.hasUnreadNotificationsFor(walletId)))
? null
: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
),
onPressed: () {
// reset unread state
ref.refresh(unreadNotificationsStateProvider);
Navigator.of(context)
.pushNamed(
NotificationsView.routeName,
arguments: walletId,
)
.then((_) {
final Set<int> unreadNotificationIds = ref
.read(unreadNotificationsStateProvider.state)
.state;
if (unreadNotificationIds.isEmpty) return;
List<Future<dynamic>> futures = [];
for (int i = 0;
i < unreadNotificationIds.length - 1;
i++) {
futures.add(ref
.read(notificationsProvider)
.markAsRead(
unreadNotificationIds.elementAt(i), false));
}
// wait for multiple to update if any
Future.wait(futures).then((_) {
// only notify listeners once
ref
.read(notificationsProvider)
.markAsRead(unreadNotificationIds.last, true);
});
});
},
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("walletViewSettingsButton"),
size: 36,
shadows: const [],
color:
Theme.of(context).extension<StackColors>()!.background,
icon: SvgPicture.asset(
Assets.svg.bars,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
width: 20,
height: 20,
),
onPressed: () {
//todo: check if print needed
// debugPrint("wallet view settings tapped");
Navigator.of(context).pushNamed(
WalletSettingsView.routeName,
arguments: Tuple4(
walletId,
ref.read(managerProvider).coin,
_currentSyncStatus,
_currentNodeStatus,
),
);
},
),
),
),
)
],
),
body: SafeArea(
child: Container(
color: Theme.of(context).extension<StackColors>()!.background,
child: Column(
);
},
child: WillPopScope(
onWillPop: _onWillPop,
child: Background(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () {
_logout();
Navigator.of(context).pop();
},
),
titleSpacing: 0,
title: Row(
children: [
const SizedBox(
height: 10,
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
width: 24,
height: 24,
),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: WalletSummary(
walletId: walletId,
managerProvider: managerProvider,
initialSyncStatus: ref.watch(managerProvider
.select((value) => value.isRefreshing))
? WalletSyncStatus.syncing
: WalletSyncStatus.synced,
),
const SizedBox(
width: 16,
),
Expanded(
child: Text(
ref.watch(
managerProvider.select((value) => value.walletName)),
style: STextStyles.navBarTitle(context),
overflow: TextOverflow.ellipsis,
),
)
],
),
actions: [
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("walletViewRadioButton"),
size: 36,
shadows: const [],
color: Theme.of(context)
.extension<StackColors>()!
.background,
icon: _buildNetworkIcon(_currentSyncStatus),
onPressed: () {
Navigator.of(context).pushNamed(
WalletNetworkSettingsView.routeName,
arguments: Tuple3(
walletId,
_currentSyncStatus,
_currentNodeStatus,
),
);
},
),
),
if (coin == Coin.firo)
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("walletViewAlertsButton"),
size: 36,
shadows: const [],
color: Theme.of(context)
.extension<StackColors>()!
.background,
icon: SvgPicture.asset(
ref.watch(notificationsProvider.select((value) =>
value.hasUnreadNotificationsFor(walletId)))
? Assets.svg.bellNew(context)
: Assets.svg.bell,
width: 20,
height: 20,
color: ref.watch(notificationsProvider.select((value) =>
value.hasUnreadNotificationsFor(walletId)))
? null
: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
),
onPressed: () {
// reset unread state
ref.refresh(unreadNotificationsStateProvider);
Navigator.of(context)
.pushNamed(
NotificationsView.routeName,
arguments: walletId,
)
.then((_) {
final Set<int> unreadNotificationIds = ref
.read(unreadNotificationsStateProvider.state)
.state;
if (unreadNotificationIds.isEmpty) return;
List<Future<dynamic>> futures = [];
for (int i = 0;
i < unreadNotificationIds.length - 1;
i++) {
futures.add(ref
.read(notificationsProvider)
.markAsRead(
unreadNotificationIds.elementAt(i), false));
}
// wait for multiple to update if any
Future.wait(futures).then((_) {
// only notify listeners once
ref
.read(notificationsProvider)
.markAsRead(unreadNotificationIds.last, true);
});
});
},
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("walletViewSettingsButton"),
size: 36,
shadows: const [],
color: Theme.of(context)
.extension<StackColors>()!
.background,
icon: SvgPicture.asset(
Assets.svg.bars,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
width: 20,
height: 20,
),
onPressed: () {
//todo: check if print needed
// debugPrint("wallet view settings tapped");
Navigator.of(context).pushNamed(
WalletSettingsView.routeName,
arguments: Tuple4(
walletId,
ref.read(managerProvider).coin,
_currentSyncStatus,
_currentNodeStatus,
),
);
},
),
),
),
],
),
body: SafeArea(
child: Container(
color: Theme.of(context).extension<StackColors>()!.background,
child: Column(
children: [
const SizedBox(
height: 10,
),
if (coin == Coin.firo)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonStyle(context),
onPressed: () async {
await showDialog<void>(
context: context,
builder: (context) => StackDialog(
title: "Attention!",
message:
"You're about to anonymize all of your public funds.",
leftButton: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Cancel",
style: STextStyles.button(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: WalletSummary(
walletId: walletId,
managerProvider: managerProvider,
initialSyncStatus: ref.watch(managerProvider
.select((value) => value.isRefreshing))
? WalletSyncStatus.syncing
: WalletSyncStatus.synced,
),
),
),
if (coin == Coin.firo)
const SizedBox(
height: 10,
),
if (coin == Coin.firo)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonStyle(context),
onPressed: () async {
await showDialog<void>(
context: context,
builder: (context) => StackDialog(
title: "Attention!",
message:
"You're about to anonymize all of your public funds.",
leftButton: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Cancel",
style: STextStyles.button(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
rightButton: TextButton(
onPressed: () async {
Navigator.of(context).pop();
unawaited(attemptAnonymize());
},
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonStyle(
context),
child: Text(
"Continue",
style: STextStyles.button(context),
),
),
),
rightButton: TextButton(
onPressed: () async {
Navigator.of(context).pop();
unawaited(attemptAnonymize());
},
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonStyle(
context),
child: Text(
"Continue",
style: STextStyles.button(context),
),
),
);
},
child: Text(
"Anonymize funds",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary,
),
);
},
child: Text(
"Anonymize funds",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary,
),
),
),
],
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Transactions",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
CustomTextButton(
text: "See all",
onTap: () {
Navigator.of(context).pushNamed(
AllTransactionsView.routeName,
arguments: walletId,
);
},
),
],
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Transactions",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
CustomTextButton(
text: "See all",
onTap: () {
Navigator.of(context).pushNamed(
AllTransactionsView.routeName,
arguments: walletId,
);
},
),
],
const SizedBox(
height: 12,
),
),
const SizedBox(
height: 12,
),
Expanded(
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Padding(
padding: const EdgeInsets.only(bottom: 14),
child: ClipRRect(
borderRadius: BorderRadius.vertical(
top: Radius.circular(
Constants.size.circularBorderRadius,
),
bottom: Radius.circular(
// WalletView.navBarHeight / 2.0,
Constants.size.circularBorderRadius,
),
),
child: Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(
Expanded(
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Padding(
padding: const EdgeInsets.only(bottom: 14),
child: ClipRRect(
borderRadius: BorderRadius.vertical(
top: Radius.circular(
Constants.size.circularBorderRadius,
),
bottom: Radius.circular(
// WalletView.navBarHeight / 2.0,
Constants.size.circularBorderRadius,
),
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Expanded(
child: TransactionsList(
managerProvider: managerProvider,
walletId: walletId,
),
child: Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
],
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Expanded(
child: TransactionsList(
managerProvider: managerProvider,
walletId: walletId,
),
),
],
),
),
),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
bottom: 14,
left: 16,
right: 16,
),
child: WalletNavigationBar(
walletId: widget.walletId,
coin: ref.watch(managerProvider
.select((value) => value.coin)),
enableExchange: Constants.enableExchange &&
ref.watch(managerProvider.select(
(value) => value.coin)) !=
Coin.epicCash,
height: WalletView.navBarHeight,
onExchangePressed: () =>
_onExchangePressed(context),
onReceivePressed: () async {
final coin =
ref.read(managerProvider).coin;
if (mounted) {
unawaited(
Navigator.of(context).pushNamed(
ReceiveView.routeName,
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
bottom: 14,
left: 16,
right: 16,
),
child: WalletNavigationBar(
walletId: widget.walletId,
coin: ref.watch(managerProvider
.select((value) => value.coin)),
enableExchange:
Constants.enableExchange &&
ref.watch(managerProvider.select(
(value) => value.coin)) !=
Coin.epicCash,
height: WalletView.navBarHeight,
onExchangePressed: () =>
_onExchangePressed(context),
onReceivePressed: () async {
final coin =
ref.read(managerProvider).coin;
if (mounted) {
unawaited(
Navigator.of(context).pushNamed(
ReceiveView.routeName,
arguments: Tuple2(
walletId,
coin,
),
));
}
},
onSendPressed: () {
final walletId =
ref.read(managerProvider).walletId;
final coin =
ref.read(managerProvider).coin;
switch (ref
.read(
walletBalanceToggleStateProvider
.state)
.state) {
case WalletBalanceToggleState.full:
ref
.read(
publicPrivateBalanceStateProvider
.state)
.state = "Public";
break;
case WalletBalanceToggleState
.available:
ref
.read(
publicPrivateBalanceStateProvider
.state)
.state = "Private";
break;
}
Navigator.of(context).pushNamed(
SendView.routeName,
arguments: Tuple2(
walletId,
coin,
),
);
},
onBuyPressed: () {
unawaited(
Navigator.of(context).pushNamed(
BuyInWalletView.routeName,
arguments: coin,
));
}
},
onSendPressed: () {
final walletId =
ref.read(managerProvider).walletId;
final coin =
ref.read(managerProvider).coin;
switch (ref
.read(walletBalanceToggleStateProvider
.state)
.state) {
case WalletBalanceToggleState.full:
ref
.read(
publicPrivateBalanceStateProvider
.state)
.state = "Public";
break;
case WalletBalanceToggleState.available:
ref
.read(
publicPrivateBalanceStateProvider
.state)
.state = "Private";
break;
}
Navigator.of(context).pushNamed(
SendView.routeName,
arguments: Tuple2(
walletId,
coin,
),
);
},
onBuyPressed: () {
unawaited(Navigator.of(context).pushNamed(
BuyInWalletView.routeName,
arguments: coin,
));
},
},
),
),
),
],
),
],
)
],
],
),
],
)
],
),
),
),
],
],
),
),
),
),

View file

@ -1,79 +1,142 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class DesktopExchangeView extends StatefulWidget {
class DesktopExchangeView extends ConsumerStatefulWidget {
const DesktopExchangeView({Key? key}) : super(key: key);
static const String routeName = "/desktopExchange";
@override
State<DesktopExchangeView> createState() => _DesktopExchangeViewState();
ConsumerState<DesktopExchangeView> createState() =>
_DesktopExchangeViewState();
}
class _DesktopExchangeViewState extends State<DesktopExchangeView> {
class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
bool _initialCachePopulationUnderway = false;
@override
void initState() {
if (!ref.read(prefsChangeNotifierProvider).externalCalls) {
if (ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
ExchangeDataLoadingService.instance
.init()
.then((_) => ExchangeDataLoadingService.instance.loadAll());
} else if (ExchangeDataLoadingService.instance.isLoading &&
ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
super.initState();
}
@override
Widget build(BuildContext context) {
return DesktopScaffold(
appBar: DesktopAppBar(
isCompactHeight: true,
leading: Padding(
return ConditionalParent(
condition: _initialCachePopulationUnderway,
builder: (child) {
return Stack(
children: [
child,
Material(
color: Theme.of(context)
.extension<StackColors>()!
.overlay
.withOpacity(0.6),
child: const CustomLoadingOverlay(
message: "Updating exchange data",
subMessage: "This could take a few minutes",
eventBus: null,
),
)
],
);
},
child: DesktopScaffold(
appBar: DesktopAppBar(
isCompactHeight: true,
leading: Padding(
padding: const EdgeInsets.only(
left: 24,
),
child: Text(
"Exchange",
style: STextStyles.desktopH3(context),
),
),
),
body: Padding(
padding: const EdgeInsets.only(
left: 24,
right: 24,
bottom: 24,
),
child: Text(
"Exchange",
style: STextStyles.desktopH3(context),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Exchange details",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
const SizedBox(
height: 16,
),
const RoundedWhiteContainer(
padding: EdgeInsets.all(24),
child: ExchangeForm(),
),
],
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Row(
children: const [
Expanded(
child: DesktopTradeHistory(),
),
],
),
),
],
),
),
),
body: Padding(
padding: const EdgeInsets.only(
left: 24,
right: 24,
bottom: 24,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Exchange details",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
const SizedBox(
height: 16,
),
const RoundedWhiteContainer(
padding: EdgeInsets.all(24),
child: ExchangeForm(),
),
],
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Row(
children: const [
Expanded(
child: DesktopTradeHistory(),
),
],
),
),
],
),
),
);
}
}

View file

@ -7,19 +7,19 @@ import 'package:qr_flutter/qr_flutter.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/pages/exchange_view/send_from_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart';
import 'package:stackwallet/providers/exchange/exchange_provider.dart';
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/services/exchange/exchange_response.dart';
import 'package:stackwallet/services/notifications_api.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -83,7 +83,8 @@ class _StepScaffoldState extends ConsumerState<StepScaffold> {
);
final ExchangeResponse<Trade> response = await ref
.read(exchangeProvider)
.read(exchangeFormStateProvider)
.exchange
.createTrade(
from: ref.read(desktopExchangeModelProvider)!.sendTicker,
to: ref.read(desktopExchangeModelProvider)!.receiveTicker,

View file

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
@ -38,7 +38,8 @@ class DesktopStep1 extends ConsumerWidget {
children: [
DesktopStepItem(
label: "Exchange",
value: ref.watch(currentExchangeNameStateProvider.state).state,
value: ref.watch(exchangeFormStateProvider
.select((value) => value.exchange.name)),
),
Container(
height: 1,

View file

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
import 'package:stackwallet/providers/exchange/current_exchange_name_state_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
@ -36,7 +36,8 @@ class _DesktopStep3State extends ConsumerState<DesktopStep3> {
children: [
DesktopStepItem(
label: "Exchange",
value: ref.watch(currentExchangeNameStateProvider.state).state,
value: ref.watch(exchangeFormStateProvider
.select((value) => value.exchange.name)),
),
Container(
height: 1,

View file

@ -45,7 +45,8 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
return;
}
final statusResponse = await ref.read(exchangeProvider).updateTrade(trade);
final statusResponse =
await ref.read(exchangeFormStateProvider).exchange.updateTrade(trade);
String status = "Waiting";
if (statusResponse.value != null) {
status = statusResponse.value!.status;

View file

@ -24,12 +24,15 @@ import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
@ -63,6 +66,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
late final EventBus eventBus;
late final bool _shouldDisableAutoSyncOnLogOut;
bool _rescanningOnOpen = false;
Future<void> onBackPressed() async {
await _logout();
@ -265,7 +269,18 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
_shouldDisableAutoSyncOnLogOut = false;
}
ref.read(managerProvider).refresh();
if (ref.read(managerProvider).rescanOnOpenVersion == Constants.rescanV1) {
_rescanningOnOpen = true;
ref.read(managerProvider).fullRescan(20, 1000).then(
(_) => ref.read(managerProvider).resetRescanOnOpen().then(
(_) => WidgetsBinding.instance.addPostFrameCallback(
(_) => setState(() => _rescanningOnOpen = false),
),
),
);
} else {
ref.read(managerProvider).refresh();
}
super.initState();
}
@ -284,241 +299,263 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
final managerProvider = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManagerProvider(widget.walletId)));
return DesktopScaffold(
appBar: DesktopAppBar(
background: Theme.of(context).extension<StackColors>()!.popupBG,
leading: Expanded(
child: Row(
children: [
const SizedBox(
width: 32,
return ConditionalParent(
condition: _rescanningOnOpen,
builder: (child) {
return Stack(
children: [
child,
Background(
child: CustomLoadingOverlay(
message:
"Migration in progress\nThis could take a while\nPlease don't leave this screen",
subMessage: "This only needs to run once per wallet",
eventBus: null,
textColor: Theme.of(context).extension<StackColors>()!.textDark,
),
AppBarIconButton(
size: 32,
color: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.arrowLeft,
width: 18,
height: 18,
)
],
);
},
child: DesktopScaffold(
appBar: DesktopAppBar(
background: Theme.of(context).extension<StackColors>()!.popupBG,
leading: Expanded(
child: Row(
children: [
const SizedBox(
width: 32,
),
AppBarIconButton(
size: 32,
color: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
.textFieldDefaultBG,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.arrowLeft,
width: 18,
height: 18,
color: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
),
onPressed: onBackPressed,
),
const SizedBox(
width: 15,
),
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
width: 32,
height: 32,
),
const SizedBox(
width: 12,
),
ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 48,
),
child: IntrinsicWidth(
child: DesktopWalletNameField(
walletId: widget.walletId,
),
),
),
const Spacer(),
Row(
children: [
NetworkInfoButton(
walletId: widget.walletId,
eventBus: eventBus,
),
const SizedBox(
width: 2,
),
WalletKeysButton(
walletId: widget.walletId,
),
const SizedBox(
width: 2,
),
DeleteWalletButton(
walletId: widget.walletId,
),
const SizedBox(
width: 12,
),
],
),
],
),
),
useSpacers: false,
isCompactHeight: true,
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
RoundedWhiteContainer(
padding: const EdgeInsets.all(20),
child: Row(
children: [
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
width: 40,
height: 40,
),
const SizedBox(
width: 10,
),
DesktopWalletSummary(
walletId: widget.walletId,
managerProvider: managerProvider,
initialSyncStatus: ref.watch(managerProvider
.select((value) => value.isRefreshing))
? WalletSyncStatus.syncing
: WalletSyncStatus.synced,
),
const Spacer(),
if (coin == Coin.firo) const SizedBox(width: 10),
if (coin == Coin.firo)
SecondaryButton(
width: 180,
buttonHeight: ButtonHeight.l,
label: "Anonymize funds",
onPressed: () async {
await showDialog<void>(
context: context,
barrierDismissible: false,
builder: (context) => DesktopDialog(
maxWidth: 500,
maxHeight: 210,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 32, vertical: 20),
child: Column(
children: [
Text(
"Attention!",
style: STextStyles.desktopH2(context),
),
const SizedBox(height: 16),
Text(
"You're about to anonymize all of your public funds.",
style:
STextStyles.desktopTextSmall(context),
),
const SizedBox(height: 32),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
SecondaryButton(
width: 200,
buttonHeight: ButtonHeight.l,
label: "Cancel",
onPressed: () {
Navigator.of(context).pop();
},
),
const SizedBox(width: 20),
PrimaryButton(
width: 200,
buttonHeight: ButtonHeight.l,
label: "Continue",
onPressed: () {
Navigator.of(context).pop();
unawaited(attemptAnonymize());
},
)
],
),
],
),
),
),
);
},
),
if (ref.watch(walletsChangeNotifierProvider.select(
(value) => value
.getManager(widget.walletId)
.hasPaynymSupport)))
SecondaryButton(
label: "PayNym",
width: 160,
buttonHeight: ButtonHeight.l,
icon: SvgPicture.asset(
Assets.svg.user,
height: 20,
width: 20,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary,
),
onPressed: onPaynymButtonPressed,
),
// if (coin == Coin.firo) const SizedBox(width: 16),
// SecondaryButton(
// width: 180,
// buttonHeight: ButtonHeight.l,
// onPressed: () {
// _onExchangePressed(context);
// },
// label: "Exchange",
// icon: Container(
// width: 24,
// height: 24,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(24),
// color: Theme.of(context)
// .extension<StackColors>()!
// .buttonBackPrimary
// .withOpacity(0.2),
// ),
// child: Center(
// child: SvgPicture.asset(
// Assets.svg.arrowRotate2,
// width: 14,
// height: 14,
// color: Theme.of(context)
// .extension<StackColors>()!
// .buttonTextSecondary,
// ),
// ),
// ),
// ),
],
),
onPressed: onBackPressed,
),
const SizedBox(
width: 15,
height: 24,
),
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
width: 32,
height: 32,
),
const SizedBox(
width: 12,
),
ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 48,
Expanded(
child: Row(
children: [
SizedBox(
width: 450,
child: MyWallet(
walletId: widget.walletId,
),
),
const SizedBox(
width: 16,
),
Expanded(
child: RecentDesktopTransactions(
walletId: widget.walletId,
),
),
],
),
child: IntrinsicWidth(
child: DesktopWalletNameField(
walletId: widget.walletId,
),
),
),
const Spacer(),
Row(
children: [
NetworkInfoButton(
walletId: widget.walletId,
eventBus: eventBus,
),
const SizedBox(
width: 2,
),
WalletKeysButton(
walletId: widget.walletId,
),
const SizedBox(
width: 2,
),
DeleteWalletButton(
walletId: widget.walletId,
),
const SizedBox(
width: 12,
),
],
),
],
),
),
useSpacers: false,
isCompactHeight: true,
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
RoundedWhiteContainer(
padding: const EdgeInsets.all(20),
child: Row(
children: [
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
width: 40,
height: 40,
),
const SizedBox(
width: 10,
),
DesktopWalletSummary(
walletId: widget.walletId,
managerProvider: managerProvider,
initialSyncStatus: ref.watch(managerProvider
.select((value) => value.isRefreshing))
? WalletSyncStatus.syncing
: WalletSyncStatus.synced,
),
const Spacer(),
if (coin == Coin.firo) const SizedBox(width: 10),
if (coin == Coin.firo)
SecondaryButton(
width: 180,
buttonHeight: ButtonHeight.l,
label: "Anonymize funds",
onPressed: () async {
await showDialog<void>(
context: context,
barrierDismissible: false,
builder: (context) => DesktopDialog(
maxWidth: 500,
maxHeight: 210,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 32, vertical: 20),
child: Column(
children: [
Text(
"Attention!",
style: STextStyles.desktopH2(context),
),
const SizedBox(height: 16),
Text(
"You're about to anonymize all of your public funds.",
style:
STextStyles.desktopTextSmall(context),
),
const SizedBox(height: 32),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SecondaryButton(
width: 200,
buttonHeight: ButtonHeight.l,
label: "Cancel",
onPressed: () {
Navigator.of(context).pop();
},
),
const SizedBox(width: 20),
PrimaryButton(
width: 200,
buttonHeight: ButtonHeight.l,
label: "Continue",
onPressed: () {
Navigator.of(context).pop();
unawaited(attemptAnonymize());
},
)
],
),
],
),
),
),
);
},
),
if (ref.watch(walletsChangeNotifierProvider.select((value) =>
value.getManager(widget.walletId).hasPaynymSupport)))
SecondaryButton(
label: "PayNym",
width: 160,
buttonHeight: ButtonHeight.l,
icon: SvgPicture.asset(
Assets.svg.user,
height: 20,
width: 20,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary,
),
onPressed: onPaynymButtonPressed,
),
// if (coin == Coin.firo) const SizedBox(width: 16),
// SecondaryButton(
// width: 180,
// buttonHeight: ButtonHeight.l,
// onPressed: () {
// _onExchangePressed(context);
// },
// label: "Exchange",
// icon: Container(
// width: 24,
// height: 24,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(24),
// color: Theme.of(context)
// .extension<StackColors>()!
// .buttonBackPrimary
// .withOpacity(0.2),
// ),
// child: Center(
// child: SvgPicture.asset(
// Assets.svg.arrowRotate2,
// width: 14,
// height: 14,
// color: Theme.of(context)
// .extension<StackColors>()!
// .buttonTextSecondary,
// ),
// ),
// ),
// ),
],
),
),
const SizedBox(
height: 24,
),
Expanded(
child: Row(
children: [
SizedBox(
width: 450,
child: MyWallet(
walletId: widget.walletId,
),
),
const SizedBox(
width: 16,
),
Expanded(
child: RecentDesktopTransactions(
walletId: widget.walletId,
),
),
],
),
),
],
),
),
);
}

View file

@ -1,6 +0,0 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
final currentExchangeNameStateProvider = StateProvider<String>(
(ref) => Exchange.defaultExchange.name,
);

View file

@ -1,9 +0,0 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/exchange/current_exchange_name_state_provider.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
final exchangeProvider = Provider<Exchange>(
(ref) => Exchange.fromName(
ref.watch(currentExchangeNameStateProvider.state).state,
),
);

View file

@ -2,10 +2,8 @@ export './buy/buy_form_state_provider.dart';
export './buy/simplex_initial_load_status.dart';
export './buy/simplex_provider.dart';
export './exchange/changenow_initial_load_status.dart';
export './exchange/current_exchange_name_state_provider.dart';
export './exchange/exchange_flow_is_active_state_provider.dart';
export './exchange/exchange_form_state_provider.dart';
export './exchange/exchange_provider.dart';
export './exchange/exchange_send_from_wallet_id_provider.dart';
export './exchange/trade_note_service_provider.dart';
export './exchange/trade_sent_from_stack_lookup_provider.dart';

View file

@ -711,15 +711,15 @@ class RouteGenerator {
return _routeError("${settings.name} invalid args: ${args.toString()}");
case RestoreWalletView.routeName:
if (args is Tuple4<String, Coin, int, DateTime>) {
if (args is Tuple5<String, Coin, int, DateTime, String>) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => RestoreWalletView(
walletName: args.item1,
coin: args.item2,
seedWordsLength: args.item3,
restoreFromDate: args.item4,
),
walletName: args.item1,
coin: args.item2,
seedWordsLength: args.item3,
restoreFromDate: args.item4,
mnemonicPassphrase: args.item5),
settings: RouteSettings(
name: settings.name,
),

View file

@ -871,7 +871,7 @@ class EpicCashWallet extends CoinServiceAPI
publicKey: [], // ??
);
await db.putAddress(address);
await db.updateOrPutAddresses([address]);
}
return address;
@ -2094,12 +2094,14 @@ class EpicCashWallet extends CoinServiceAPI
height = null;
}
final isIncoming = (tx["tx_type"] == "TxReceived" ||
tx["tx_type"] == "TxReceivedCancelled");
final txn = isar_models.Transaction(
walletId: walletId,
txid: commitId ?? tx["id"].toString(),
timestamp: (dt.millisecondsSinceEpoch ~/ 1000),
type: (tx["tx_type"] == "TxReceived" ||
tx["tx_type"] == "TxReceivedCancelled")
type: isIncoming
? isar_models.TransactionType.incoming
: isar_models.TransactionType.outgoing,
subType: isar_models.TransactionSubType.none,
@ -2122,6 +2124,38 @@ class EpicCashWallet extends CoinServiceAPI
.filter()
.valueEqualTo(address)
.findFirst();
if (transactionAddress == null) {
if (isIncoming) {
transactionAddress = isar_models.Address(
walletId: walletId,
value: address,
publicKey: [],
derivationIndex: 0,
derivationPath: null,
type: isar_models.AddressType.mimbleWimble,
subType: isar_models.AddressSubType.receiving,
);
} else {
final myRcvAddr = await currentReceivingAddress;
final isSentToSelf = myRcvAddr == address;
transactionAddress = isar_models.Address(
walletId: walletId,
value: address,
publicKey: [],
derivationIndex: isSentToSelf ? 0 : -1,
derivationPath: null,
type: isSentToSelf
? isar_models.AddressType.mimbleWimble
: isar_models.AddressType.nonWallet,
subType: isSentToSelf
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.nonWallet,
);
}
}
//
// midSortedTx["inputSize"] = tx["num_inputs"];
// midSortedTx["outputSize"] = tx["num_outputs"];

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/models.dart';
@ -227,4 +228,18 @@ class Manager with ChangeNotifier {
int get currentHeight => _currentWallet.storedChainHeight;
bool get hasPaynymSupport => _currentWallet is PaynymWalletInterface;
int get rescanOnOpenVersion =>
DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo,
key: "rescan_on_open_$walletId",
) as int? ??
0;
Future<void> resetRescanOnOpen() async {
await DB.instance.delete<dynamic>(
key: "rescan_on_open_$walletId",
boxName: DB.boxNameDBInfo,
);
}
}

View file

@ -434,8 +434,27 @@ class ChangeNowAPI {
final json = await _makeGetRequest(uri);
try {
final value = EstimatedExchangeAmount.fromJson(
Map<String, dynamic>.from(json as Map));
final map = Map<String, dynamic>.from(json as Map);
if (map["error"] != null) {
if (map["error"] == "not_valid_fixed_rate_pair") {
return ExchangeResponse(
exception: PairUnavailableException(
map["message"] as String? ?? "Unsupported fixed rate pair",
ExchangeExceptionType.generic,
),
);
} else {
return ExchangeResponse(
exception: ExchangeException(
map["message"] as String? ?? map["error"].toString(),
ExchangeExceptionType.generic,
),
);
}
}
final value = EstimatedExchangeAmount.fromJson(map);
return ExchangeResponse(
value: Estimate(
estimatedAmount: value.estimatedAmount,

View file

@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
@ -16,6 +17,25 @@ class ExchangeDataLoadingService {
Isar? _isar;
Isar get isar => _isar!;
VoidCallback? onLoadingError;
VoidCallback? onLoadingComplete;
static const int cacheVersion = 1;
static int get currentCacheVersion =>
DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo,
key: "exchange_data_cache_version") as int? ??
0;
Future<void> _updateCurrentCacheVersion(int version) async {
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo,
key: "exchange_data_cache_version",
value: version,
);
}
Future<void> init() async {
if (_isar != null && isar.isOpen) return;
_isar = await Isar.open(
@ -25,18 +45,23 @@ class ExchangeDataLoadingService {
],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
inspector: kDebugMode,
// inspector: false,
name: "exchange_cache",
);
}
bool get isLoading => _locked;
bool _locked = false;
Future<void> loadAll() async {
print("LOADINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG: LOCKED=$_locked");
if (!_locked) {
_locked = true;
print("LOADINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");
final time = DateTime.now();
Logging.instance.log(
"ExchangeDataLoadingService.loadAll starting...",
level: LogLevel.Info,
);
final start = DateTime.now();
try {
await Future.wait([
_loadChangeNowCurrencies(),
@ -46,13 +71,18 @@ class ExchangeDataLoadingService {
// loadSimpleswapFloatingRateCurrencies(ref),
loadMajesticBankCurrencies(),
]);
print(
"LOADINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG done in ${DateTime.now().difference(time).inSeconds} seconds");
Logging.instance.log(
"ExchangeDataLoadingService.loadAll finished in ${DateTime.now().difference(start).inSeconds} seconds",
level: LogLevel.Info,
);
onLoadingComplete?.call();
await _updateCurrentCacheVersion(cacheVersion);
} catch (e, s) {
Logging.instance.log(
"ExchangeDataLoadingService.loadAll failed: $e\n$s",
level: LogLevel.Error);
"ExchangeDataLoadingService.loadAll failed after ${DateTime.now().difference(start).inSeconds} seconds: $e\n$s",
level: LogLevel.Error,
);
onLoadingError?.call();
}
_locked = false;
}
@ -82,7 +112,7 @@ class ExchangeDataLoadingService {
Future<void> _loadChangeNowFixedRatePairs() async {
final exchange = ChangeNowExchange.instance;
final responsePairs = await exchange.getAllPairs(true);
final responsePairs = await compute(exchange.getAllPairs, true);
if (responsePairs.value != null) {
await isar.writeTxn(() async {
@ -107,7 +137,7 @@ class ExchangeDataLoadingService {
Future<void> _loadChangeNowEstimatedRatePairs() async {
final exchange = ChangeNowExchange.instance;
final responsePairs = await exchange.getAllPairs(false);
final responsePairs = await compute(exchange.getAllPairs, false);
if (responsePairs.value != null) {
await isar.writeTxn(() async {

View file

@ -21,7 +21,8 @@ abstract class Constants {
}
static bool enableExchange = Util.isDesktop || !Platform.isIOS;
static bool enableBuy = true; // true for development, TODO change to "Util.isDesktop || !Platform.isIOS;" as above or even just = enableExchange
static bool enableBuy =
true; // true for development, TODO change to "Util.isDesktop || !Platform.isIOS;" as above or even just = enableExchange
//TODO: correct for monero?
static const int _satsPerCoinMonero = 1000000000000;
@ -41,6 +42,8 @@ abstract class Constants {
static const int currentHiveDbVersion = 5;
static const int rescanV1 = 1;
static int satsPerCoin(Coin coin) {
switch (coin) {
case Coin.bitcoin:

View file

@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:hive/hive.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
@ -12,10 +10,10 @@ import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:tuple/tuple.dart';
@ -200,6 +198,7 @@ class DbVersionMigrator with WalletDB {
final prefs = Prefs.instance;
final walletInfoList = await walletsService.walletNames;
await prefs.init();
await MainDB.instance.initMainDB();
for (final walletId in walletInfoList.keys) {
final info = walletInfoList[walletId]!;
@ -207,206 +206,67 @@ class DbVersionMigrator with WalletDB {
final walletBox = await Hive.openBox<dynamic>(info.walletId);
final receiveDerivePrefix = "${walletId}_receiveDerivations";
final changeDerivePrefix = "${walletId}_changeDerivations";
const receiveAddressesPrefix = "receivingAddresses";
const changeAddressesPrefix = "changeAddresses";
final p2pkhRcvDerivations =
(await secureStore.read(key: receiveDerivePrefix)) ??
(await secureStore.read(key: "${receiveDerivePrefix}P2PKH"));
final p2shRcvDerivations =
await secureStore.read(key: "${receiveDerivePrefix}P2SH");
final p2wpkhRcvDerivations =
await secureStore.read(key: "${receiveDerivePrefix}P2WPKH");
// we need to manually migrate epic cash transactions as they are not
// stored on the epic cash blockchain
if (info.coin == Coin.epicCash) {
final txnData = walletBox.get("latest_tx_model") as TransactionData?;
final p2pkhCngDerivations =
(await secureStore.read(key: changeDerivePrefix)) ??
(await secureStore.read(key: "${changeDerivePrefix}P2PKH"));
final p2shCngDerivations =
await secureStore.read(key: "${changeDerivePrefix}P2SH");
final p2wpkhCngDerivations =
await secureStore.read(key: "${changeDerivePrefix}P2WPKH");
// we ever only used index 0 in the past
const rcvIndex = 0;
// useless?
// const receiveIndexPrefix = "receivingIndex";
// const changeIndexPrefix = "changeIndex";
// final p2pkhRcvIndex = walletBox.get(receiveIndexPrefix) as int? ??
// walletBox.get("${receiveIndexPrefix}P2PKH") as int?;
// final p2shRcvIndex =
// walletBox.get("${receiveIndexPrefix}P2SH") as int?;
// final p2wpkhRcvIndex =
// walletBox.get("${receiveIndexPrefix}P2WPKH") as int?;
//
// final p2pkhCngIndex = walletBox.get(changeIndexPrefix) as int? ??
// walletBox.get("${changeIndexPrefix}P2PKH") as int?;
// final p2shCngIndex =
// walletBox.get("${changeIndexPrefix}P2SH") as int?;
// final p2wpkhCngIndex =
// walletBox.get("${changeIndexPrefix}P2WPKH") as int?;
final List<Tuple2<isar_models.Transaction, isar_models.Address?>>
transactionsData = [];
if (txnData != null) {
final txns = txnData.getAllTransactions();
final List<isar_models.Address> newAddresses = [];
for (final tx in txns.values) {
bool isIncoming = tx.txType == "Received";
if (p2pkhRcvDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2pkhRcvDerivations,
isar_models.AddressType.p2pkh,
isar_models.AddressSubType.receiving,
walletId,
),
);
}
final iTx = isar_models.Transaction(
walletId: walletId,
txid: tx.txid,
timestamp: tx.timestamp,
type: isIncoming
? isar_models.TransactionType.incoming
: isar_models.TransactionType.outgoing,
subType: isar_models.TransactionSubType.none,
amount: tx.amount,
fee: tx.fees,
height: tx.height,
isCancelled: tx.isCancelled,
isLelantus: false,
slateId: tx.slateId,
otherData: tx.otherData,
inputs: [],
outputs: [],
);
if (p2shRcvDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2shRcvDerivations,
isar_models.AddressType.p2sh,
isar_models.AddressSubType.receiving,
walletId,
),
);
}
if (p2wpkhRcvDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2wpkhRcvDerivations,
isar_models.AddressType.p2wpkh,
isar_models.AddressSubType.receiving,
walletId,
),
);
}
if (p2pkhCngDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2pkhCngDerivations,
isar_models.AddressType.p2pkh,
isar_models.AddressSubType.change,
walletId,
),
);
}
if (p2shCngDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2shCngDerivations,
isar_models.AddressType.p2sh,
isar_models.AddressSubType.change,
walletId,
),
);
}
if (p2wpkhCngDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2wpkhCngDerivations,
isar_models.AddressType.p2wpkh,
isar_models.AddressSubType.change,
walletId,
),
);
}
final currentNewSet = newAddresses.map((e) => e.value).toSet();
final p2pkhRcvAddresses = _v4GetAddressesFromList(
_getList(walletBox.get(receiveAddressesPrefix) ??
walletBox.get("${receiveAddressesPrefix}P2PKH")),
isar_models.AddressType.p2pkh,
isar_models.AddressSubType.receiving,
walletId);
for (final address in p2pkhRcvAddresses) {
if (!currentNewSet.contains(address.value)) {
newAddresses.add(address);
if (tx.address.isEmpty) {
transactionsData.add(Tuple2(iTx, null));
} else {
final address = isar_models.Address(
walletId: walletId,
value: tx.address,
publicKey: [],
derivationIndex: isIncoming ? rcvIndex : -1,
derivationPath: null,
type: isIncoming
? isar_models.AddressType.mimbleWimble
: isar_models.AddressType.unknown,
subType: isIncoming
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.unknown,
);
transactionsData.add(Tuple2(iTx, address));
}
}
}
await MainDB.instance.addNewTransactionData(transactionsData, walletId);
}
final p2shRcvAddresses = _v4GetAddressesFromList(
_getList(walletBox.get("${receiveAddressesPrefix}P2SH")),
isar_models.AddressType.p2sh,
isar_models.AddressSubType.receiving,
walletId);
for (final address in p2shRcvAddresses) {
if (!currentNewSet.contains(address.value)) {
newAddresses.add(address);
}
}
final p2wpkhRcvAddresses = _v4GetAddressesFromList(
_getList(walletBox.get("${receiveAddressesPrefix}P2WPKH")),
isar_models.AddressType.p2wpkh,
isar_models.AddressSubType.receiving,
walletId);
for (final address in p2wpkhRcvAddresses) {
if (!currentNewSet.contains(address.value)) {
newAddresses.add(address);
}
}
final p2pkhCngAddresses = _v4GetAddressesFromList(
_getList(walletBox.get(changeAddressesPrefix) ??
walletBox.get("${changeAddressesPrefix}P2PKH")),
isar_models.AddressType.p2wpkh,
isar_models.AddressSubType.change,
walletId);
for (final address in p2pkhCngAddresses) {
if (!currentNewSet.contains(address.value)) {
newAddresses.add(address);
}
}
final p2shCngAddresses = _v4GetAddressesFromList(
_getList(walletBox.get("${changeAddressesPrefix}P2SH")),
isar_models.AddressType.p2wpkh,
isar_models.AddressSubType.change,
walletId);
for (final address in p2shCngAddresses) {
if (!currentNewSet.contains(address.value)) {
newAddresses.add(address);
}
}
final p2wpkhCngAddresses = _v4GetAddressesFromList(
_getList(walletBox.get("${changeAddressesPrefix}P2WPKH")),
isar_models.AddressType.p2wpkh,
isar_models.AddressSubType.change,
walletId);
for (final address in p2wpkhCngAddresses) {
if (!currentNewSet.contains(address.value)) {
newAddresses.add(address);
}
}
// transactions
final txnData = walletBox.get("latest_tx_model") as TransactionData?;
final txns = txnData?.getAllTransactions().values ?? [];
final txnDataLelantus =
walletBox.get("latest_lelantus_tx_model") as TransactionData?;
final txnsLelantus = txnDataLelantus?.getAllTransactions().values ?? [];
final List<Tuple2<isar_models.Transaction, isar_models.Address?>>
newTransactions = [];
newTransactions
.addAll(_parseTransactions(txns, walletId, false, newAddresses));
newTransactions.addAll(
_parseTransactions(txnsLelantus, walletId, true, newAddresses));
// store newly parsed data in isar
await MainDB.instance.initMainDB();
initWalletDB();
await db.isar.writeTxn(() async {
await db.isar.addresses.putAll(newAddresses);
});
await db.addNewTransactionData(newTransactions, walletId);
// delete data from hive
await walletBox.delete(receiveAddressesPrefix);
await walletBox.delete("${receiveAddressesPrefix}P2PKH");
@ -418,154 +278,24 @@ class DbVersionMigrator with WalletDB {
await walletBox.delete("${changeAddressesPrefix}P2WPKH");
await walletBox.delete("latest_tx_model");
await walletBox.delete("latest_lelantus_tx_model");
}
}
List<Tuple2<isar_models.Transaction, isar_models.Address?>>
_parseTransactions(
Iterable<Transaction> txns,
String walletId,
bool isLelantus,
List<isar_models.Address> parsedAddresses,
) {
List<Tuple2<isar_models.Transaction, isar_models.Address?>> transactions =
[];
for (final tx in txns) {
final type = tx.txType.toLowerCase() == "received"
? isar_models.TransactionType.incoming
: isar_models.TransactionType.outgoing;
final subType = tx.subType.toLowerCase() == "mint"
? isar_models.TransactionSubType.mint
: tx.subType.toLowerCase() == "join"
? isar_models.TransactionSubType.join
: isar_models.TransactionSubType.none;
// set empty mnemonic passphrase as we used that by default before
if ((await secureStore.read(key: '${walletId}_mnemonicPassphrase')) ==
null) {
await secureStore.write(
key: '${walletId}_mnemonicPassphrase', value: "");
}
final List<isar_models.Input> inputs = [];
final List<isar_models.Output> outputs = [];
for (final inp in tx.inputs) {
final input = isar_models.Input(
txid: inp.txid,
vout: inp.vout,
scriptSig: inp.scriptsig,
scriptSigAsm: inp.scriptsigAsm,
isCoinbase: inp.isCoinbase,
sequence: inp.sequence,
innerRedeemScriptAsm: inp.innerRedeemscriptAsm,
// doing this for epic cash will delete transaction history as it is not
// stored on the epic cash blockchain
if (info.coin != Coin.epicCash) {
// set flag to initiate full rescan on opening wallet
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo,
key: "rescan_on_open_$walletId",
value: Constants.rescanV1,
);
inputs.add(input);
}
for (final out in tx.outputs) {
final output = isar_models.Output(
scriptPubKey: out.scriptpubkey,
scriptPubKeyAsm: out.scriptpubkeyAsm,
scriptPubKeyType: out.scriptpubkeyType,
scriptPubKeyAddress: out.scriptpubkeyAddress,
value: out.value,
);
outputs.add(output);
}
final transaction = isar_models.Transaction(
walletId: walletId,
txid: tx.txid,
timestamp: tx.timestamp,
type: type,
subType: subType,
amount: tx.amount,
fee: tx.fees,
height: tx.height,
isCancelled: tx.isCancelled,
isLelantus: false,
slateId: tx.slateId,
otherData: tx.otherData,
inputs: inputs,
outputs: outputs,
);
isar_models.Address? address;
if (tx.address.isNotEmpty) {
final addresses = parsedAddresses.where((e) => e.value == tx.address);
if (addresses.isNotEmpty) {
address = addresses.first;
} else {
address = isar_models.Address(
walletId: walletId,
value: tx.address,
publicKey: [],
derivationIndex: -1,
derivationPath: null,
type: isar_models.AddressType.unknown,
subType: type == isar_models.TransactionType.incoming
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.unknown,
);
}
}
transactions.add(Tuple2(transaction, address));
}
return transactions;
}
List<isar_models.Address> _v4GetAddressesFromDerivationString(
String derivationsString,
isar_models.AddressType type,
isar_models.AddressSubType subType,
String walletId,
) {
final List<isar_models.Address> addresses = [];
final derivations =
Map<String, dynamic>.from(jsonDecode(derivationsString) as Map);
for (final entry in derivations.entries) {
final addr = entry.value["address"] as String? ?? entry.key;
final pubKey = entry.value["pubKey"] as String? ??
entry.value["publicKey"] as String;
final index = int.tryParse(entry.key) ?? -1;
final address = isar_models.Address(
walletId: walletId,
value: addr,
publicKey: Format.stringToUint8List(pubKey),
derivationIndex: index,
derivationPath: null, // we have no idea what the full path is
type: type,
subType: subType,
);
addresses.add(address);
}
return addresses;
}
List<isar_models.Address> _v4GetAddressesFromList(
List<String> addressStrings,
isar_models.AddressType type,
isar_models.AddressSubType subType,
String walletId,
) {
final List<isar_models.Address> addresses = [];
for (final addr in addressStrings) {
final address = isar_models.Address(
walletId: walletId,
value: addr,
publicKey: [],
derivationIndex: -1,
derivationPath: null, // index unknown
type: type,
subType: subType,
);
addresses.add(address);
}
return addresses;
}
List<String> _getList(dynamic list) {
if (list == null) return [];
return List<String>.from(list as List);
}
}

View file

@ -0,0 +1 @@
enum ExchangeRateType { estimated, fixed }

View file

@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/languages_enum.dart';
@ -18,7 +17,7 @@ class Prefs extends ChangeNotifier {
Future<void> init() async {
if (!_initialized) {
_currency = await _getPreferredCurrency();
_exchangeRateType = await _getExchangeRateType();
// _exchangeRateType = await _getExchangeRateType();
_useBiometrics = await _getUseBiometrics();
_hasPin = await _getHasPin();
_language = await _getPreferredLanguage();
@ -251,44 +250,44 @@ class Prefs extends ChangeNotifier {
// exchange rate type
ExchangeRateType _exchangeRateType = ExchangeRateType.estimated;
ExchangeRateType get exchangeRateType => _exchangeRateType;
set exchangeRateType(ExchangeRateType exchangeRateType) {
if (_exchangeRateType != exchangeRateType) {
switch (exchangeRateType) {
case ExchangeRateType.estimated:
DB.instance.put<dynamic>(
boxName: DB.boxNamePrefs,
key: "exchangeRateType",
value: "estimated");
break;
case ExchangeRateType.fixed:
DB.instance.put<dynamic>(
boxName: DB.boxNamePrefs,
key: "exchangeRateType",
value: "fixed");
break;
}
_exchangeRateType = exchangeRateType;
notifyListeners();
}
}
Future<ExchangeRateType> _getExchangeRateType() async {
String? rate = await DB.instance.get<dynamic>(
boxName: DB.boxNamePrefs, key: "exchangeRateType") as String?;
rate ??= "estimated";
switch (rate) {
case "estimated":
return ExchangeRateType.estimated;
case "fixed":
return ExchangeRateType.fixed;
default:
throw Exception("Invalid exchange rate type found in prefs!");
}
}
// ExchangeRateType _exchangeRateType = ExchangeRateType.estimated;
//
// ExchangeRateType get exchangeRateType => _exchangeRateType;
//
// set exchangeRateType(ExchangeRateType exchangeRateType) {
// if (_exchangeRateType != exchangeRateType) {
// switch (exchangeRateType) {
// case ExchangeRateType.estimated:
// DB.instance.put<dynamic>(
// boxName: DB.boxNamePrefs,
// key: "exchangeRateType",
// value: "estimated");
// break;
// case ExchangeRateType.fixed:
// DB.instance.put<dynamic>(
// boxName: DB.boxNamePrefs,
// key: "exchangeRateType",
// value: "fixed");
// break;
// }
// _exchangeRateType = exchangeRateType;
// notifyListeners();
// }
// }
//
// Future<ExchangeRateType> _getExchangeRateType() async {
// String? rate = await DB.instance.get<dynamic>(
// boxName: DB.boxNamePrefs, key: "exchangeRateType") as String?;
// rate ??= "estimated";
// switch (rate) {
// case "estimated":
// return ExchangeRateType.estimated;
// case "fixed":
// return ExchangeRateType.fixed;
// default:
// throw Exception("Invalid exchange rate type found in prefs!");
// }
// }
// use biometrics

View file

@ -11,11 +11,15 @@ class CustomLoadingOverlay extends ConsumerStatefulWidget {
const CustomLoadingOverlay({
Key? key,
required this.message,
this.subMessage,
required this.eventBus,
this.textColor,
}) : super(key: key);
final String message;
final String? subMessage;
final EventBus? eventBus;
final Color? textColor;
@override
ConsumerState<CustomLoadingOverlay> createState() =>
@ -56,10 +60,12 @@ class _CustomLoadingOverlayState extends ConsumerState<CustomLoadingOverlay> {
children: [
Text(
widget.message,
textAlign: TextAlign.center,
style: STextStyles.pageTitleH2(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.loadingOverlayTextColor,
color: widget.textColor ??
Theme.of(context)
.extension<StackColors>()!
.loadingOverlayTextColor,
),
),
if (widget.eventBus != null)
@ -70,11 +76,28 @@ class _CustomLoadingOverlayState extends ConsumerState<CustomLoadingOverlay> {
Text(
"${(_percent * 100).toStringAsFixed(2)}%",
style: STextStyles.pageTitleH2(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.loadingOverlayTextColor,
color: widget.textColor ??
Theme.of(context)
.extension<StackColors>()!
.loadingOverlayTextColor,
),
),
if (widget.subMessage != null)
const SizedBox(
height: 10,
),
if (widget.subMessage != null)
Text(
widget.subMessage!,
textAlign: TextAlign.center,
style: STextStyles.pageTitleH2(context).copyWith(
fontSize: 14,
color: widget.textColor ??
Theme.of(context)
.extension<StackColors>()!
.loadingOverlayTextColor,
),
)
],
),
),

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -23,8 +24,7 @@ class ExchangeTextField extends StatefulWidget {
this.onSubmitted,
this.onTap,
required this.isWalletCoin,
this.image,
this.ticker,
this.currency,
this.readOnly = false,
}) : super(key: key);
@ -42,8 +42,7 @@ class ExchangeTextField extends StatefulWidget {
final bool isWalletCoin;
final bool readOnly;
final String? image;
final String? ticker;
final AggregateCurrency? currency;
@override
State<ExchangeTextField> createState() => _ExchangeTextFieldState();
@ -115,7 +114,7 @@ class _ExchangeTextFieldState extends State<ExchangeTextField> {
top: 12,
left: 12,
),
hintText: "0",
hintText: widget.currency == null ? "select currency" : "0",
hintStyle: STextStyles.fieldLabel(context).copyWith(
fontSize: 14,
),
@ -157,18 +156,18 @@ class _ExchangeTextFieldState extends State<ExchangeTextField> {
),
child: Builder(
builder: (context) {
if (isStackCoin(widget.ticker)) {
if (isStackCoin(widget.currency?.ticker)) {
return Center(
child: getIconForTicker(
widget.ticker!,
widget.currency!.ticker,
size: 18,
),
);
} else if (widget.image != null &&
widget.image!.isNotEmpty) {
} else if (widget.currency != null &&
widget.currency!.image.isNotEmpty) {
return Center(
child: SvgPicture.network(
widget.image!,
widget.currency!.image,
height: 18,
placeholderBuilder: (_) => Container(
width: 18,
@ -215,7 +214,7 @@ class _ExchangeTextFieldState extends State<ExchangeTextField> {
width: 6,
),
Text(
widget.ticker?.toUpperCase() ?? "-",
widget.currency?.ticker.toUpperCase() ?? "n/a",
style: STextStyles.smallMed14(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!

View file

@ -4,14 +4,12 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i4;
import 'dart:ui' as _i9;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i2;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i3;
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart'
as _i7;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i8;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i7;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i6;
import 'package:stackwallet/utilities/prefs.dart' as _i5;
@ -511,20 +509,6 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: null,
);
@override
_i7.ExchangeRateType get exchangeRateType => (super.noSuchMethod(
Invocation.getter(#exchangeRateType),
returnValue: _i7.ExchangeRateType.estimated,
) as _i7.ExchangeRateType);
@override
set exchangeRateType(_i7.ExchangeRateType? exchangeRateType) =>
super.noSuchMethod(
Invocation.setter(
#exchangeRateType,
exchangeRateType,
),
returnValueForMissingStub: null,
);
@override
bool get useBiometrics => (super.noSuchMethod(
Invocation.getter(#useBiometrics),
returnValue: false,
@ -598,12 +582,12 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: null,
);
@override
_i8.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
_i7.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
Invocation.getter(#backupFrequencyType),
returnValue: _i8.BackupFrequencyType.everyTenMinutes,
) as _i8.BackupFrequencyType);
returnValue: _i7.BackupFrequencyType.everyTenMinutes,
) as _i7.BackupFrequencyType);
@override
set backupFrequencyType(_i8.BackupFrequencyType? backupFrequencyType) =>
set backupFrequencyType(_i7.BackupFrequencyType? backupFrequencyType) =>
super.noSuchMethod(
Invocation.setter(
#backupFrequencyType,
@ -717,7 +701,7 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: _i4.Future<void>.value(),
) as _i4.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -725,7 +709,7 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: null,
);
@override
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -4,13 +4,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i3;
import 'dart:ui' as _i8;
import 'dart:ui' as _i7;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/electrumx_rpc/rpc.dart' as _i2;
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart'
as _i6;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i7;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i6;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i5;
import 'package:stackwallet/utilities/prefs.dart' as _i4;
@ -232,20 +230,6 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: null,
);
@override
_i6.ExchangeRateType get exchangeRateType => (super.noSuchMethod(
Invocation.getter(#exchangeRateType),
returnValue: _i6.ExchangeRateType.estimated,
) as _i6.ExchangeRateType);
@override
set exchangeRateType(_i6.ExchangeRateType? exchangeRateType) =>
super.noSuchMethod(
Invocation.setter(
#exchangeRateType,
exchangeRateType,
),
returnValueForMissingStub: null,
);
@override
bool get useBiometrics => (super.noSuchMethod(
Invocation.getter(#useBiometrics),
returnValue: false,
@ -319,12 +303,12 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: null,
);
@override
_i7.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
_i6.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
Invocation.getter(#backupFrequencyType),
returnValue: _i7.BackupFrequencyType.everyTenMinutes,
) as _i7.BackupFrequencyType);
returnValue: _i6.BackupFrequencyType.everyTenMinutes,
) as _i6.BackupFrequencyType);
@override
set backupFrequencyType(_i7.BackupFrequencyType? backupFrequencyType) =>
set backupFrequencyType(_i6.BackupFrequencyType? backupFrequencyType) =>
super.noSuchMethod(
Invocation.setter(
#backupFrequencyType,
@ -438,7 +422,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: _i3.Future<void>.value(),
) as _i3.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -446,7 +430,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -19,8 +19,6 @@ import 'package:stackwallet/models/balance.dart' as _i12;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i16;
import 'package:stackwallet/models/node_model.dart' as _i24;
import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i9;
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart'
as _i30;
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i25;
import 'package:stackwallet/services/coins/coin_service.dart' as _i18;
import 'package:stackwallet/services/coins/manager.dart' as _i6;
@ -30,7 +28,7 @@ import 'package:stackwallet/services/transaction_notification_tracker.dart'
as _i8;
import 'package:stackwallet/services/wallets.dart' as _i19;
import 'package:stackwallet/services/wallets_service.dart' as _i2;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i31;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i30;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i20;
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i26;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i29;
@ -2307,20 +2305,6 @@ class MockPrefs extends _i1.Mock implements _i22.Prefs {
returnValueForMissingStub: null,
);
@override
_i30.ExchangeRateType get exchangeRateType => (super.noSuchMethod(
Invocation.getter(#exchangeRateType),
returnValue: _i30.ExchangeRateType.estimated,
) as _i30.ExchangeRateType);
@override
set exchangeRateType(_i30.ExchangeRateType? exchangeRateType) =>
super.noSuchMethod(
Invocation.setter(
#exchangeRateType,
exchangeRateType,
),
returnValueForMissingStub: null,
);
@override
bool get useBiometrics => (super.noSuchMethod(
Invocation.getter(#useBiometrics),
returnValue: false,
@ -2394,12 +2378,12 @@ class MockPrefs extends _i1.Mock implements _i22.Prefs {
returnValueForMissingStub: null,
);
@override
_i31.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
_i30.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
Invocation.getter(#backupFrequencyType),
returnValue: _i31.BackupFrequencyType.everyTenMinutes,
) as _i31.BackupFrequencyType);
returnValue: _i30.BackupFrequencyType.everyTenMinutes,
) as _i30.BackupFrequencyType);
@override
set backupFrequencyType(_i31.BackupFrequencyType? backupFrequencyType) =>
set backupFrequencyType(_i30.BackupFrequencyType? backupFrequencyType) =>
super.noSuchMethod(
Invocation.setter(
#backupFrequencyType,
@ -2693,6 +2677,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -2858,6 +2847,15 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i21.Future<bool>.value(false),
) as _i21.Future<bool>);
@override
_i21.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i21.Future<void>.value(),
returnValueForMissingStub: _i21.Future<void>.value(),
) as _i21.Future<void>);
@override
void addListener(_i23.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -373,6 +373,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -538,6 +543,15 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -334,6 +334,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -499,6 +504,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -332,6 +332,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -497,6 +502,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -3,36 +3,33 @@
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'dart:async' as _i6;
import 'dart:ui' as _i7;
import 'package:decimal/decimal.dart' as _i15;
import 'package:http/http.dart' as _i13;
import 'package:decimal/decimal.dart' as _i14;
import 'package:http/http.dart' as _i12;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/exchange/change_now/cn_exchange_estimate.dart'
as _i18;
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'
as _i20;
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'
as _i21;
import 'package:stackwallet/models/exchange/response_objects/estimate.dart'
as _i17;
import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart'
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'
as _i19;
import 'package:stackwallet/models/exchange/response_objects/range.dart'
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'
as _i20;
import 'package:stackwallet/models/exchange/response_objects/estimate.dart'
as _i16;
import 'package:stackwallet/models/exchange/response_objects/trade.dart'
as _i10;
import 'package:stackwallet/models/isar/exchange_cache/currency.dart' as _i14;
import 'package:stackwallet/models/isar/exchange_cache/pair.dart' as _i22;
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart'
as _i5;
import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart'
as _i18;
import 'package:stackwallet/models/exchange/response_objects/range.dart'
as _i15;
import 'package:stackwallet/models/exchange/response_objects/trade.dart' as _i9;
import 'package:stackwallet/models/isar/exchange_cache/currency.dart' as _i13;
import 'package:stackwallet/models/isar/exchange_cache/pair.dart' as _i21;
import 'package:stackwallet/services/exchange/change_now/change_now_api.dart'
as _i12;
as _i11;
import 'package:stackwallet/services/exchange/exchange_response.dart' as _i2;
import 'package:stackwallet/services/trade_notes_service.dart' as _i11;
import 'package:stackwallet/services/trade_service.dart' as _i9;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i6;
import 'package:stackwallet/services/trade_notes_service.dart' as _i10;
import 'package:stackwallet/services/trade_service.dart' as _i8;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i5;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i4;
import 'package:stackwallet/utilities/prefs.dart' as _i3;
@ -182,20 +179,6 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
returnValueForMissingStub: null,
);
@override
_i5.ExchangeRateType get exchangeRateType => (super.noSuchMethod(
Invocation.getter(#exchangeRateType),
returnValue: _i5.ExchangeRateType.estimated,
) as _i5.ExchangeRateType);
@override
set exchangeRateType(_i5.ExchangeRateType? exchangeRateType) =>
super.noSuchMethod(
Invocation.setter(
#exchangeRateType,
exchangeRateType,
),
returnValueForMissingStub: null,
);
@override
bool get useBiometrics => (super.noSuchMethod(
Invocation.getter(#useBiometrics),
returnValue: false,
@ -269,12 +252,12 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
returnValueForMissingStub: null,
);
@override
_i6.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
_i5.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
Invocation.getter(#backupFrequencyType),
returnValue: _i6.BackupFrequencyType.everyTenMinutes,
) as _i6.BackupFrequencyType);
returnValue: _i5.BackupFrequencyType.everyTenMinutes,
) as _i5.BackupFrequencyType);
@override
set backupFrequencyType(_i6.BackupFrequencyType? backupFrequencyType) =>
set backupFrequencyType(_i5.BackupFrequencyType? backupFrequencyType) =>
super.noSuchMethod(
Invocation.setter(
#backupFrequencyType,
@ -344,51 +327,51 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
returnValue: false,
) as bool);
@override
_i7.Future<void> init() => (super.noSuchMethod(
_i6.Future<void> init() => (super.noSuchMethod(
Invocation.method(
#init,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<void> incrementCurrentNotificationIndex() => (super.noSuchMethod(
_i6.Future<void> incrementCurrentNotificationIndex() => (super.noSuchMethod(
Invocation.method(
#incrementCurrentNotificationIndex,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<bool> isExternalCallsSet() => (super.noSuchMethod(
_i6.Future<bool> isExternalCallsSet() => (super.noSuchMethod(
Invocation.method(
#isExternalCallsSet,
[],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i7.Future<void> saveUserID(String? userId) => (super.noSuchMethod(
_i6.Future<void> saveUserID(String? userId) => (super.noSuchMethod(
Invocation.method(
#saveUserID,
[userId],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<void> saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod(
_i6.Future<void> saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod(
Invocation.method(
#saveSignupEpoch,
[signupEpoch],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -396,7 +379,7 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@ -424,29 +407,29 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
/// A class which mocks [TradesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockTradesService extends _i1.Mock implements _i9.TradesService {
class MockTradesService extends _i1.Mock implements _i8.TradesService {
MockTradesService() {
_i1.throwOnMissingStub(this);
}
@override
List<_i10.Trade> get trades => (super.noSuchMethod(
List<_i9.Trade> get trades => (super.noSuchMethod(
Invocation.getter(#trades),
returnValue: <_i10.Trade>[],
) as List<_i10.Trade>);
returnValue: <_i9.Trade>[],
) as List<_i9.Trade>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i10.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method(
_i9.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method(
#get,
[tradeId],
)) as _i10.Trade?);
)) as _i9.Trade?);
@override
_i7.Future<void> add({
required _i10.Trade? trade,
_i6.Future<void> add({
required _i9.Trade? trade,
required bool? shouldNotifyListeners,
}) =>
(super.noSuchMethod(
@ -458,12 +441,12 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<void> edit({
required _i10.Trade? trade,
_i6.Future<void> edit({
required _i9.Trade? trade,
required bool? shouldNotifyListeners,
}) =>
(super.noSuchMethod(
@ -475,12 +458,12 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<void> delete({
required _i10.Trade? trade,
_i6.Future<void> delete({
required _i9.Trade? trade,
required bool? shouldNotifyListeners,
}) =>
(super.noSuchMethod(
@ -492,11 +475,11 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<void> deleteByUuid({
_i6.Future<void> deleteByUuid({
required String? uuid,
required bool? shouldNotifyListeners,
}) =>
@ -509,11 +492,11 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -521,7 +504,7 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@ -549,7 +532,7 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
/// A class which mocks [TradeNotesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockTradeNotesService extends _i1.Mock implements _i11.TradeNotesService {
class MockTradeNotesService extends _i1.Mock implements _i10.TradeNotesService {
MockTradeNotesService() {
_i1.throwOnMissingStub(this);
}
@ -574,7 +557,7 @@ class MockTradeNotesService extends _i1.Mock implements _i11.TradeNotesService {
returnValue: '',
) as String);
@override
_i7.Future<void> set({
_i6.Future<void> set({
required String? tradeId,
required String? note,
}) =>
@ -587,21 +570,21 @@ class MockTradeNotesService extends _i1.Mock implements _i11.TradeNotesService {
#note: note,
},
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i7.Future<void> delete({required String? tradeId}) => (super.noSuchMethod(
_i6.Future<void> delete({required String? tradeId}) => (super.noSuchMethod(
Invocation.method(
#delete,
[],
{#tradeId: tradeId},
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -609,7 +592,7 @@ class MockTradeNotesService extends _i1.Mock implements _i11.TradeNotesService {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@ -637,13 +620,13 @@ class MockTradeNotesService extends _i1.Mock implements _i11.TradeNotesService {
/// A class which mocks [ChangeNowAPI].
///
/// See the documentation for Mockito's code generation for more information.
class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
MockChangeNowAPI() {
_i1.throwOnMissingStub(this);
}
@override
set client(_i13.Client? _client) => super.noSuchMethod(
set client(_i12.Client? _client) => super.noSuchMethod(
Invocation.setter(
#client,
_client,
@ -651,7 +634,7 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
returnValueForMissingStub: null,
);
@override
_i7.Future<_i2.ExchangeResponse<List<_i14.Currency>>> getAvailableCurrencies({
_i6.Future<_i2.ExchangeResponse<List<_i13.Currency>>> getAvailableCurrencies({
bool? fixedRate,
bool? active,
}) =>
@ -665,8 +648,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
returnValue:
_i7.Future<_i2.ExchangeResponse<List<_i14.Currency>>>.value(
_FakeExchangeResponse_0<List<_i14.Currency>>(
_i6.Future<_i2.ExchangeResponse<List<_i13.Currency>>>.value(
_FakeExchangeResponse_0<List<_i13.Currency>>(
this,
Invocation.method(
#getAvailableCurrencies,
@ -677,9 +660,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<List<_i14.Currency>>>);
) as _i6.Future<_i2.ExchangeResponse<List<_i13.Currency>>>);
@override
_i7.Future<_i2.ExchangeResponse<List<_i14.Currency>>> getPairedCurrencies({
_i6.Future<_i2.ExchangeResponse<List<_i13.Currency>>> getPairedCurrencies({
required String? ticker,
bool? fixedRate,
}) =>
@ -693,8 +676,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
returnValue:
_i7.Future<_i2.ExchangeResponse<List<_i14.Currency>>>.value(
_FakeExchangeResponse_0<List<_i14.Currency>>(
_i6.Future<_i2.ExchangeResponse<List<_i13.Currency>>>.value(
_FakeExchangeResponse_0<List<_i13.Currency>>(
this,
Invocation.method(
#getPairedCurrencies,
@ -705,9 +688,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<List<_i14.Currency>>>);
) as _i6.Future<_i2.ExchangeResponse<List<_i13.Currency>>>);
@override
_i7.Future<_i2.ExchangeResponse<_i15.Decimal>> getMinimalExchangeAmount({
_i6.Future<_i2.ExchangeResponse<_i14.Decimal>> getMinimalExchangeAmount({
required String? fromTicker,
required String? toTicker,
String? apiKey,
@ -722,8 +705,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<_i2.ExchangeResponse<_i15.Decimal>>.value(
_FakeExchangeResponse_0<_i15.Decimal>(
returnValue: _i6.Future<_i2.ExchangeResponse<_i14.Decimal>>.value(
_FakeExchangeResponse_0<_i14.Decimal>(
this,
Invocation.method(
#getMinimalExchangeAmount,
@ -735,9 +718,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i15.Decimal>>);
) as _i6.Future<_i2.ExchangeResponse<_i14.Decimal>>);
@override
_i7.Future<_i2.ExchangeResponse<_i16.Range>> getRange({
_i6.Future<_i2.ExchangeResponse<_i15.Range>> getRange({
required String? fromTicker,
required String? toTicker,
required bool? isFixedRate,
@ -754,8 +737,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<_i2.ExchangeResponse<_i16.Range>>.value(
_FakeExchangeResponse_0<_i16.Range>(
returnValue: _i6.Future<_i2.ExchangeResponse<_i15.Range>>.value(
_FakeExchangeResponse_0<_i15.Range>(
this,
Invocation.method(
#getRange,
@ -768,12 +751,12 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i16.Range>>);
) as _i6.Future<_i2.ExchangeResponse<_i15.Range>>);
@override
_i7.Future<_i2.ExchangeResponse<_i17.Estimate>> getEstimatedExchangeAmount({
_i6.Future<_i2.ExchangeResponse<_i16.Estimate>> getEstimatedExchangeAmount({
required String? fromTicker,
required String? toTicker,
required _i15.Decimal? fromAmount,
required _i14.Decimal? fromAmount,
String? apiKey,
}) =>
(super.noSuchMethod(
@ -787,8 +770,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>.value(
_FakeExchangeResponse_0<_i17.Estimate>(
returnValue: _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>.value(
_FakeExchangeResponse_0<_i16.Estimate>(
this,
Invocation.method(
#getEstimatedExchangeAmount,
@ -801,13 +784,13 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>);
) as _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>);
@override
_i7.Future<_i2.ExchangeResponse<_i17.Estimate>>
_i6.Future<_i2.ExchangeResponse<_i16.Estimate>>
getEstimatedExchangeAmountFixedRate({
required String? fromTicker,
required String? toTicker,
required _i15.Decimal? fromAmount,
required _i14.Decimal? fromAmount,
required bool? reversed,
bool? useRateId = true,
String? apiKey,
@ -825,8 +808,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>.value(
_FakeExchangeResponse_0<_i17.Estimate>(
returnValue: _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>.value(
_FakeExchangeResponse_0<_i16.Estimate>(
this,
Invocation.method(
#getEstimatedExchangeAmountFixedRate,
@ -841,17 +824,17 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>);
) as _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>);
@override
_i7.Future<_i2.ExchangeResponse<_i18.CNExchangeEstimate>>
_i6.Future<_i2.ExchangeResponse<_i17.CNExchangeEstimate>>
getEstimatedExchangeAmountV2({
required String? fromTicker,
required String? toTicker,
required _i18.CNEstimateType? fromOrTo,
required _i15.Decimal? amount,
required _i17.CNEstimateType? fromOrTo,
required _i14.Decimal? amount,
String? fromNetwork,
String? toNetwork,
_i18.CNFlowType? flow = _i18.CNFlowType.standard,
_i17.CNFlowType? flow = _i17.CNFlowType.standard,
String? apiKey,
}) =>
(super.noSuchMethod(
@ -870,8 +853,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
returnValue:
_i7.Future<_i2.ExchangeResponse<_i18.CNExchangeEstimate>>.value(
_FakeExchangeResponse_0<_i18.CNExchangeEstimate>(
_i6.Future<_i2.ExchangeResponse<_i17.CNExchangeEstimate>>.value(
_FakeExchangeResponse_0<_i17.CNExchangeEstimate>(
this,
Invocation.method(
#getEstimatedExchangeAmountV2,
@ -888,18 +871,18 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i18.CNExchangeEstimate>>);
) as _i6.Future<_i2.ExchangeResponse<_i17.CNExchangeEstimate>>);
@override
_i7.Future<_i2.ExchangeResponse<List<_i19.FixedRateMarket>>>
_i6.Future<_i2.ExchangeResponse<List<_i18.FixedRateMarket>>>
getAvailableFixedRateMarkets({String? apiKey}) => (super.noSuchMethod(
Invocation.method(
#getAvailableFixedRateMarkets,
[],
{#apiKey: apiKey},
),
returnValue: _i7.Future<
_i2.ExchangeResponse<List<_i19.FixedRateMarket>>>.value(
_FakeExchangeResponse_0<List<_i19.FixedRateMarket>>(
returnValue: _i6.Future<
_i2.ExchangeResponse<List<_i18.FixedRateMarket>>>.value(
_FakeExchangeResponse_0<List<_i18.FixedRateMarket>>(
this,
Invocation.method(
#getAvailableFixedRateMarkets,
@ -907,14 +890,14 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
{#apiKey: apiKey},
),
)),
) as _i7.Future<_i2.ExchangeResponse<List<_i19.FixedRateMarket>>>);
) as _i6.Future<_i2.ExchangeResponse<List<_i18.FixedRateMarket>>>);
@override
_i7.Future<_i2.ExchangeResponse<_i20.ExchangeTransaction>>
_i6.Future<_i2.ExchangeResponse<_i19.ExchangeTransaction>>
createStandardExchangeTransaction({
required String? fromTicker,
required String? toTicker,
required String? receivingAddress,
required _i15.Decimal? amount,
required _i14.Decimal? amount,
String? extraId = r'',
String? userId = r'',
String? contactEmail = r'',
@ -939,9 +922,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<
_i2.ExchangeResponse<_i20.ExchangeTransaction>>.value(
_FakeExchangeResponse_0<_i20.ExchangeTransaction>(
returnValue: _i6.Future<
_i2.ExchangeResponse<_i19.ExchangeTransaction>>.value(
_FakeExchangeResponse_0<_i19.ExchangeTransaction>(
this,
Invocation.method(
#createStandardExchangeTransaction,
@ -960,14 +943,14 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i20.ExchangeTransaction>>);
) as _i6.Future<_i2.ExchangeResponse<_i19.ExchangeTransaction>>);
@override
_i7.Future<_i2.ExchangeResponse<_i20.ExchangeTransaction>>
_i6.Future<_i2.ExchangeResponse<_i19.ExchangeTransaction>>
createFixedRateExchangeTransaction({
required String? fromTicker,
required String? toTicker,
required String? receivingAddress,
required _i15.Decimal? amount,
required _i14.Decimal? amount,
required String? rateId,
required bool? reversed,
String? extraId = r'',
@ -996,9 +979,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<
_i2.ExchangeResponse<_i20.ExchangeTransaction>>.value(
_FakeExchangeResponse_0<_i20.ExchangeTransaction>(
returnValue: _i6.Future<
_i2.ExchangeResponse<_i19.ExchangeTransaction>>.value(
_FakeExchangeResponse_0<_i19.ExchangeTransaction>(
this,
Invocation.method(
#createFixedRateExchangeTransaction,
@ -1019,9 +1002,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7.Future<_i2.ExchangeResponse<_i20.ExchangeTransaction>>);
) as _i6.Future<_i2.ExchangeResponse<_i19.ExchangeTransaction>>);
@override
_i7.Future<_i2.ExchangeResponse<_i21.ExchangeTransactionStatus>>
_i6.Future<_i2.ExchangeResponse<_i20.ExchangeTransactionStatus>>
getTransactionStatus({
required String? id,
String? apiKey,
@ -1035,9 +1018,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
#apiKey: apiKey,
},
),
returnValue: _i7.Future<
_i2.ExchangeResponse<_i21.ExchangeTransactionStatus>>.value(
_FakeExchangeResponse_0<_i21.ExchangeTransactionStatus>(
returnValue: _i6.Future<
_i2.ExchangeResponse<_i20.ExchangeTransactionStatus>>.value(
_FakeExchangeResponse_0<_i20.ExchangeTransactionStatus>(
this,
Invocation.method(
#getTransactionStatus,
@ -1048,10 +1031,10 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
},
),
)),
) as _i7
.Future<_i2.ExchangeResponse<_i21.ExchangeTransactionStatus>>);
) as _i6
.Future<_i2.ExchangeResponse<_i20.ExchangeTransactionStatus>>);
@override
_i7.Future<_i2.ExchangeResponse<List<_i22.Pair>>>
_i6.Future<_i2.ExchangeResponse<List<_i21.Pair>>>
getAvailableFloatingRatePairs({bool? includePartners = false}) =>
(super.noSuchMethod(
Invocation.method(
@ -1060,8 +1043,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
{#includePartners: includePartners},
),
returnValue:
_i7.Future<_i2.ExchangeResponse<List<_i22.Pair>>>.value(
_FakeExchangeResponse_0<List<_i22.Pair>>(
_i6.Future<_i2.ExchangeResponse<List<_i21.Pair>>>.value(
_FakeExchangeResponse_0<List<_i21.Pair>>(
this,
Invocation.method(
#getAvailableFloatingRatePairs,
@ -1069,5 +1052,5 @@ class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
{#includePartners: includePartners},
),
)),
) as _i7.Future<_i2.ExchangeResponse<List<_i22.Pair>>>);
) as _i6.Future<_i2.ExchangeResponse<List<_i21.Pair>>>);
}

View file

@ -641,6 +641,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -806,6 +811,15 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -428,6 +428,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -593,6 +598,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -428,6 +428,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -593,6 +598,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -428,6 +428,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -593,6 +598,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -203,6 +203,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -368,6 +373,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -426,6 +426,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -591,6 +596,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -641,6 +641,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -806,6 +811,15 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -482,6 +482,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -647,6 +652,15 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
void addListener(_i11.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -203,6 +203,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -368,6 +373,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -203,6 +203,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -368,6 +373,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -583,6 +588,15 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -583,6 +588,15 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -203,6 +203,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -368,6 +373,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -203,6 +203,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -368,6 +373,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -426,6 +426,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -591,6 +596,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -683,6 +683,11 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -848,6 +853,15 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
void addListener(_i14.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -426,6 +426,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -591,6 +596,15 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -205,6 +205,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -370,6 +375,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -204,6 +204,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -369,6 +374,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -203,6 +203,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -368,6 +373,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -245,6 +245,11 @@ class MockManager extends _i1.Mock implements _i8.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -410,6 +415,15 @@ class MockManager extends _i1.Mock implements _i8.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i11.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -205,6 +205,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -370,6 +375,15 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -2320,6 +2320,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -2485,6 +2490,15 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i21.Future<bool>.value(false),
) as _i21.Future<bool>);
@override
_i21.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i21.Future<void>.value(),
returnValueForMissingStub: _i21.Future<void>.value(),
) as _i21.Future<void>);
@override
void addListener(_i23.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -9,14 +9,12 @@ import 'dart:ui' as _i12;
import 'package:flutter/foundation.dart' as _i4;
import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/node_model.dart' as _i16;
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart'
as _i14;
import 'package:stackwallet/models/node_model.dart' as _i15;
import 'package:stackwallet/services/coins/manager.dart' as _i6;
import 'package:stackwallet/services/node_service.dart' as _i3;
import 'package:stackwallet/services/wallets.dart' as _i8;
import 'package:stackwallet/services/wallets_service.dart' as _i2;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i15;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i14;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i9;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i13;
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'
@ -416,20 +414,6 @@ class MockPrefs extends _i1.Mock implements _i11.Prefs {
returnValueForMissingStub: null,
);
@override
_i14.ExchangeRateType get exchangeRateType => (super.noSuchMethod(
Invocation.getter(#exchangeRateType),
returnValue: _i14.ExchangeRateType.estimated,
) as _i14.ExchangeRateType);
@override
set exchangeRateType(_i14.ExchangeRateType? exchangeRateType) =>
super.noSuchMethod(
Invocation.setter(
#exchangeRateType,
exchangeRateType,
),
returnValueForMissingStub: null,
);
@override
bool get useBiometrics => (super.noSuchMethod(
Invocation.getter(#useBiometrics),
returnValue: false,
@ -503,12 +487,12 @@ class MockPrefs extends _i1.Mock implements _i11.Prefs {
returnValueForMissingStub: null,
);
@override
_i15.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
_i14.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
Invocation.getter(#backupFrequencyType),
returnValue: _i15.BackupFrequencyType.everyTenMinutes,
) as _i15.BackupFrequencyType);
returnValue: _i14.BackupFrequencyType.everyTenMinutes,
) as _i14.BackupFrequencyType);
@override
set backupFrequencyType(_i15.BackupFrequencyType? backupFrequencyType) =>
set backupFrequencyType(_i14.BackupFrequencyType? backupFrequencyType) =>
super.noSuchMethod(
Invocation.setter(
#backupFrequencyType,
@ -672,15 +656,15 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService {
),
) as _i7.SecureStorageInterface);
@override
List<_i16.NodeModel> get primaryNodes => (super.noSuchMethod(
List<_i15.NodeModel> get primaryNodes => (super.noSuchMethod(
Invocation.getter(#primaryNodes),
returnValue: <_i16.NodeModel>[],
) as List<_i16.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
List<_i16.NodeModel> get nodes => (super.noSuchMethod(
List<_i15.NodeModel> get nodes => (super.noSuchMethod(
Invocation.getter(#nodes),
returnValue: <_i16.NodeModel>[],
) as List<_i16.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
@ -698,7 +682,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService {
@override
_i10.Future<void> setPrimaryNodeFor({
required _i9.Coin? coin,
required _i16.NodeModel? node,
required _i15.NodeModel? node,
bool? shouldNotifyListeners = false,
}) =>
(super.noSuchMethod(
@ -715,40 +699,40 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService {
returnValueForMissingStub: _i10.Future<void>.value(),
) as _i10.Future<void>);
@override
_i16.NodeModel? getPrimaryNodeFor({required _i9.Coin? coin}) =>
_i15.NodeModel? getPrimaryNodeFor({required _i9.Coin? coin}) =>
(super.noSuchMethod(Invocation.method(
#getPrimaryNodeFor,
[],
{#coin: coin},
)) as _i16.NodeModel?);
)) as _i15.NodeModel?);
@override
List<_i16.NodeModel> getNodesFor(_i9.Coin? coin) => (super.noSuchMethod(
List<_i15.NodeModel> getNodesFor(_i9.Coin? coin) => (super.noSuchMethod(
Invocation.method(
#getNodesFor,
[coin],
),
returnValue: <_i16.NodeModel>[],
) as List<_i16.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
_i16.NodeModel? getNodeById({required String? id}) =>
_i15.NodeModel? getNodeById({required String? id}) =>
(super.noSuchMethod(Invocation.method(
#getNodeById,
[],
{#id: id},
)) as _i16.NodeModel?);
)) as _i15.NodeModel?);
@override
List<_i16.NodeModel> failoverNodesFor({required _i9.Coin? coin}) =>
List<_i15.NodeModel> failoverNodesFor({required _i9.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#failoverNodesFor,
[],
{#coin: coin},
),
returnValue: <_i16.NodeModel>[],
) as List<_i16.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
_i10.Future<void> add(
_i16.NodeModel? node,
_i15.NodeModel? node,
String? password,
bool? shouldNotifyListeners,
) =>
@ -800,7 +784,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService {
) as _i10.Future<void>);
@override
_i10.Future<void> edit(
_i16.NodeModel? editedNode,
_i15.NodeModel? editedNode,
String? password,
bool? shouldNotifyListeners,
) =>

View file

@ -2045,6 +2045,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -2210,6 +2215,15 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i20.Future<bool>.value(false),
) as _i20.Future<bool>);
@override
_i20.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i20.Future<void>.value(),
returnValueForMissingStub: _i20.Future<void>.value(),
) as _i20.Future<void>);
@override
void addListener(_i22.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -16,20 +16,18 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i11;
import 'package:stackwallet/models/balance.dart' as _i9;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i21;
import 'package:stackwallet/models/models.dart' as _i8;
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart'
as _i25;
import 'package:stackwallet/services/coins/coin_service.dart' as _i7;
import 'package:stackwallet/services/coins/firo/firo_wallet.dart' as _i22;
import 'package:stackwallet/services/coins/manager.dart' as _i6;
import 'package:stackwallet/services/locale_service.dart' as _i23;
import 'package:stackwallet/services/node_service.dart' as _i3;
import 'package:stackwallet/services/notes_service.dart' as _i28;
import 'package:stackwallet/services/price_service.dart' as _i27;
import 'package:stackwallet/services/notes_service.dart' as _i27;
import 'package:stackwallet/services/price_service.dart' as _i26;
import 'package:stackwallet/services/transaction_notification_tracker.dart'
as _i10;
import 'package:stackwallet/services/wallets.dart' as _i16;
import 'package:stackwallet/services/wallets_service.dart' as _i2;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i26;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i25;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i17;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i24;
import 'package:stackwallet/utilities/prefs.dart' as _i19;
@ -548,6 +546,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -713,6 +716,15 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i18.Future<bool>.value(false),
) as _i18.Future<bool>);
@override
_i18.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i18.Future<void>.value(),
returnValueForMissingStub: _i18.Future<void>.value(),
) as _i18.Future<void>);
@override
void addListener(_i20.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
@ -2164,20 +2176,6 @@ class MockPrefs extends _i1.Mock implements _i19.Prefs {
returnValueForMissingStub: null,
);
@override
_i25.ExchangeRateType get exchangeRateType => (super.noSuchMethod(
Invocation.getter(#exchangeRateType),
returnValue: _i25.ExchangeRateType.estimated,
) as _i25.ExchangeRateType);
@override
set exchangeRateType(_i25.ExchangeRateType? exchangeRateType) =>
super.noSuchMethod(
Invocation.setter(
#exchangeRateType,
exchangeRateType,
),
returnValueForMissingStub: null,
);
@override
bool get useBiometrics => (super.noSuchMethod(
Invocation.getter(#useBiometrics),
returnValue: false,
@ -2251,12 +2249,12 @@ class MockPrefs extends _i1.Mock implements _i19.Prefs {
returnValueForMissingStub: null,
);
@override
_i26.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
_i25.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod(
Invocation.getter(#backupFrequencyType),
returnValue: _i26.BackupFrequencyType.everyTenMinutes,
) as _i26.BackupFrequencyType);
returnValue: _i25.BackupFrequencyType.everyTenMinutes,
) as _i25.BackupFrequencyType);
@override
set backupFrequencyType(_i26.BackupFrequencyType? backupFrequencyType) =>
set backupFrequencyType(_i25.BackupFrequencyType? backupFrequencyType) =>
super.noSuchMethod(
Invocation.setter(
#backupFrequencyType,
@ -2406,7 +2404,7 @@ class MockPrefs extends _i1.Mock implements _i19.Prefs {
/// A class which mocks [PriceService].
///
/// See the documentation for Mockito's code generation for more information.
class MockPriceService extends _i1.Mock implements _i27.PriceService {
class MockPriceService extends _i1.Mock implements _i26.PriceService {
MockPriceService() {
_i1.throwOnMissingStub(this);
}
@ -2514,7 +2512,7 @@ class MockPriceService extends _i1.Mock implements _i27.PriceService {
/// A class which mocks [NotesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockNotesService extends _i1.Mock implements _i28.NotesService {
class MockNotesService extends _i1.Mock implements _i27.NotesService {
MockNotesService() {
_i1.throwOnMissingStub(this);
}

View file

@ -2257,6 +2257,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -2422,6 +2427,15 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i21.Future<bool>.value(false),
) as _i21.Future<bool>);
@override
_i21.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i21.Future<void>.value(),
returnValueForMissingStub: _i21.Future<void>.value(),
) as _i21.Future<void>);
@override
void addListener(_i23.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,

View file

@ -2257,6 +2257,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -2422,6 +2427,15 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i21.Future<bool>.value(false),
) as _i21.Future<bool>);
@override
_i21.Future<void> resetRescanOnOpen() => (super.noSuchMethod(
Invocation.method(
#resetRescanOnOpen,
[],
),
returnValue: _i21.Future<void>.value(),
returnValueForMissingStub: _i21.Future<void>.value(),
) as _i21.Future<void>);
@override
void addListener(_i23.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,