Merge branch 'isar-transactions' into paynyms

This commit is contained in:
julian 2023-01-20 10:23:31 -06:00
commit 7d4b6a1382
138 changed files with 31616 additions and 26590 deletions
.gitignore
lib
db
hive
main.dart
models
pages
pages_desktop_specific
providers/blockchain/dogecoin
route_generator.dart
services
utilities
widgets
pubspec.lockpubspec.yaml
test

1
.gitignore vendored
View file

@ -55,3 +55,4 @@ libcw_monero.dll
libcw_wownero.dll
libepic_cash_wallet.dll
libmobileliblelantus.dll
/libisar.so

236
lib/db/main_db.dart Normal file
View file

@ -0,0 +1,236 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
import 'package:tuple/tuple.dart';
class MainDB {
MainDB._();
static MainDB? _instance;
static MainDB get instance => _instance ??= MainDB._();
Isar? _isar;
Isar get isar => _isar!;
Future<bool> isarInit({Isar? mock}) async {
if (mock != null) {
_isar = mock;
return true;
}
if (_isar != null && isar.isOpen) return false;
_isar = await Isar.open(
[
TransactionSchema,
TransactionNoteSchema,
InputSchema,
OutputSchema,
UTXOSchema,
AddressSchema,
],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
inspector: true,
name: "wallet_data",
);
return true;
}
// addresses
QueryBuilder<Address, Address, QAfterWhereClause> getAddresses(
String walletId) =>
isar.addresses.where().walletIdEqualTo(walletId);
Future<void> putAddress(Address address) => isar.writeTxn(() async {
await isar.addresses.put(address);
});
Future<void> putAddresses(List<Address> addresses) => isar.writeTxn(() async {
await isar.addresses.putAll(addresses);
});
Future<void> updateAddress(Address oldAddress, Address newAddress) =>
isar.writeTxn(() async {
newAddress.id = oldAddress.id;
await oldAddress.transactions.load();
final txns = oldAddress.transactions.toList();
await isar.addresses.delete(oldAddress.id);
await isar.addresses.put(newAddress);
newAddress.transactions.addAll(txns);
await newAddress.transactions.save();
});
// transactions
QueryBuilder<Transaction, Transaction, QAfterWhereClause> getTransactions(
String walletId) =>
isar.transactions.where().walletIdEqualTo(walletId);
Future<void> putTransaction(Transaction transaction) =>
isar.writeTxn(() async {
await isar.transactions.put(transaction);
});
Future<void> putTransactions(List<Transaction> transactions) =>
isar.writeTxn(() async {
await isar.transactions.putAll(transactions);
});
// utxos
QueryBuilder<UTXO, UTXO, QAfterWhereClause> getUTXOs(String walletId) =>
isar.utxos.where().walletIdEqualTo(walletId);
Future<void> putUTXO(UTXO utxo) => isar.writeTxn(() async {
await isar.utxos.put(utxo);
});
Future<void> putUTXOs(List<UTXO> utxos) => isar.writeTxn(() async {
await isar.utxos.putAll(utxos);
});
// inputs
QueryBuilder<Input, Input, QAfterWhereClause> getInputs(String walletId) =>
isar.inputs.where().walletIdEqualTo(walletId);
Future<void> putInput(Input input) => isar.writeTxn(() async {
await isar.inputs.put(input);
});
Future<void> putInputs(List<Input> inputs) => isar.writeTxn(() async {
await isar.inputs.putAll(inputs);
});
// outputs
QueryBuilder<Output, Output, QAfterWhereClause> getOutputs(String walletId) =>
isar.outputs.where().walletIdEqualTo(walletId);
Future<void> putOutput(Output output) => isar.writeTxn(() async {
await isar.outputs.put(output);
});
Future<void> putOutputs(List<Output> outputs) => isar.writeTxn(() async {
await isar.outputs.putAll(outputs);
});
// transaction notes
QueryBuilder<TransactionNote, TransactionNote, QAfterWhereClause>
getTransactionNotes(String walletId) =>
isar.transactionNotes.where().walletIdEqualTo(walletId);
Future<void> putTransactionNote(TransactionNote transactionNote) =>
isar.writeTxn(() async {
await isar.transactionNotes.put(transactionNote);
});
Future<void> putTransactionNotes(List<TransactionNote> transactionNotes) =>
isar.writeTxn(() async {
await isar.transactionNotes.putAll(transactionNotes);
});
//
Future<void> deleteWalletBlockchainData(String walletId) async {
final transactionCount = await getTransactions(walletId).count();
final addressCount = await getAddresses(walletId).count();
final utxoCount = await getUTXOs(walletId).count();
final inputCount = await getInputs(walletId).count();
final outputCount = await getOutputs(walletId).count();
await isar.writeTxn(() async {
const paginateLimit = 50;
// transactions
for (int i = 0; i < transactionCount; i += paginateLimit) {
final txns = await getTransactions(walletId)
.offset(i)
.limit(paginateLimit)
.findAll();
await isar.transactions
.deleteAll(txns.map((e) => e.id).toList(growable: false));
}
// addresses
for (int i = 0; i < addressCount; i += paginateLimit) {
final addresses = await getAddresses(walletId)
.offset(i)
.limit(paginateLimit)
.findAll();
await isar.addresses
.deleteAll(addresses.map((e) => e.id).toList(growable: false));
}
// utxos
for (int i = 0; i < utxoCount; i += paginateLimit) {
final utxos =
await getUTXOs(walletId).offset(i).limit(paginateLimit).findAll();
await isar.utxos
.deleteAll(utxos.map((e) => e.id).toList(growable: false));
}
// inputs
for (int i = 0; i < inputCount; i += paginateLimit) {
final inputs =
await getInputs(walletId).offset(i).limit(paginateLimit).findAll();
await isar.inputs
.deleteAll(inputs.map((e) => e.id).toList(growable: false));
}
// outputs
for (int i = 0; i < outputCount; i += paginateLimit) {
final outputs =
await getOutputs(walletId).offset(i).limit(paginateLimit).findAll();
await isar.outputs
.deleteAll(outputs.map((e) => e.id).toList(growable: false));
}
});
}
Future<void> addNewTransactionData(
List<Tuple4<Transaction, List<Output>, List<Input>, Address?>>
transactionsData,
String walletId) async {
await isar.writeTxn(() async {
for (final data in transactionsData) {
final tx = data.item1;
final potentiallyUnconfirmedTx = await getTransactions(walletId)
.filter()
.txidEqualTo(tx.txid)
.findFirst();
if (potentiallyUnconfirmedTx != null) {
// update use id to replace tx
tx.id = potentiallyUnconfirmedTx.id;
await isar.transactions.delete(potentiallyUnconfirmedTx.id);
}
// save transaction
await isar.transactions.put(tx);
// link and save outputs
if (data.item2.isNotEmpty) {
await isar.outputs.putAll(data.item2);
tx.outputs.addAll(data.item2);
await tx.outputs.save();
}
// link and save inputs
if (data.item3.isNotEmpty) {
await isar.inputs.putAll(data.item3);
tx.inputs.addAll(data.item3);
await tx.inputs.save();
}
if (data.item4 != null) {
final address = await getAddresses(walletId)
.filter()
.valueEqualTo(data.item4!.value)
.findFirst();
// check if address exists in db and add if it does not
if (address == null) {
await isar.addresses.put(data.item4!);
}
// link and save address
tx.address.value = address ?? data.item4!;
await tx.address.save();
}
}
});
}
}

View file

@ -245,3 +245,11 @@ class DB {
Future<void> deleteBoxFromDisk({required String boxName}) async =>
await mutex.protect(() async => await Hive.deleteBoxFromDisk(boxName));
}
abstract class DBKeys {
static const String cachedBalance = "cachedBalance";
static const String cachedBalanceSecondary = "cachedBalanceSecondary";
static const String isFavorite = "isFavorite";
static const String id = "id";
static const String storedChainHeight = "storedChainHeight";
}

View file

@ -63,6 +63,8 @@ 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);
@ -155,7 +157,7 @@ void main() async {
await Hive.openBox<dynamic>(DB.boxNameDBInfo);
// todo: db migrate stuff for desktop needs to be handled eventually
// Desktop migrate handled elsewhere (currently desktop_login_view.dart)
if (!Util.isDesktop) {
int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
@ -170,7 +172,7 @@ void main() async {
),
);
} catch (e, s) {
Logging.instance.log("Cannot migrate database\n$e $s",
Logging.instance.log("Cannot migrate mobile database\n$e $s",
level: LogLevel.Error, printFullLength: true);
}
}
@ -263,6 +265,8 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
await loadShared();
}
await MainDB.instance.isarInit();
_notificationsService = ref.read(notificationsProvider);
_nodeService = ref.read(nodeServiceChangeNotifierProvider);
_tradesService = ref.read(tradesServiceProvider);

59
lib/models/balance.dart Normal file
View file

@ -0,0 +1,59 @@
import 'dart:convert';
import 'package:decimal/decimal.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
class Balance {
final Coin coin;
final int total;
final int spendable;
final int blockedTotal;
final int pendingSpendable;
Balance({
required this.coin,
required this.total,
required this.spendable,
required this.blockedTotal,
required this.pendingSpendable,
});
Decimal getTotal({bool includeBlocked = false}) => Format.satoshisToAmount(
includeBlocked ? total : total - blockedTotal,
coin: coin,
);
Decimal getSpendable() => Format.satoshisToAmount(
spendable,
coin: coin,
);
Decimal getPending() => Format.satoshisToAmount(
pendingSpendable,
coin: coin,
);
Decimal getBlocked() => Format.satoshisToAmount(
blockedTotal,
coin: coin,
);
String toJsonIgnoreCoin() => jsonEncode({
"total": total,
"spendable": spendable,
"blockedTotal": blockedTotal,
"pendingSpendable": pendingSpendable,
});
factory Balance.fromJson(String json, Coin coin) {
final decoded = jsonDecode(json);
return Balance(
coin: coin,
total: decoded["total"] as int,
spendable: decoded["spendable"] as int,
blockedTotal: decoded["blockedTotal"] as int,
pendingSpendable: decoded["pendingSpendable"] as int,
);
}
}

View file

@ -0,0 +1,94 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/address/crypto_currency_address.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
part 'address.g.dart';
class AddressException extends SWException {
AddressException(super.message);
}
@Collection(accessor: "addresses")
class Address extends CryptoCurrencyAddress {
Address({
required this.walletId,
required this.value,
required this.publicKey,
required this.derivationIndex,
required this.type,
required this.subType,
this.otherData,
});
Id id = Isar.autoIncrement;
@Index()
late final String walletId;
@Index(unique: true, composite: [CompositeIndex("walletId")])
late final String value;
late final List<byte> publicKey;
@Index()
late final int derivationIndex; // -1 generally means unknown
@enumerated
late final AddressType type;
@enumerated
late final AddressSubType subType;
late final String? otherData;
final transactions = IsarLinks<Transaction>();
int derivationChain() {
if (subType == AddressSubType.receiving) {
return 0; // 0 for receiving (external)
} else if (subType == AddressSubType.change) {
return 1; // 1 for change (internal)
} else {
throw AddressException("Could not imply derivation chain value");
}
}
bool isPaynymAddress() =>
subType == AddressSubType.paynymNotification ||
subType == AddressSubType.paynymSend ||
subType == AddressSubType.paynymReceive;
@override
String toString() => "{ "
"id: $id, "
"walletId: $walletId, "
"value: $value, "
"publicKey: $publicKey, "
"derivationIndex: $derivationIndex, "
"type: ${type.name}, "
"subType: ${subType.name}, "
"transactionsLength: ${transactions.length} "
"otherData: $otherData, "
"}";
}
enum AddressType {
p2pkh,
p2sh,
p2wpkh,
cryptonote,
mimbleWimble,
unknown,
nonWallet,
}
enum AddressSubType {
receiving,
change,
paynymNotification,
paynymSend,
paynymReceive,
unknown,
nonWallet,
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
abstract class CryptoCurrencyAddress {
// future use?
}

View file

@ -0,0 +1,46 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/output.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
part 'input.g.dart';
@Collection()
class Input {
Input({
required this.walletId,
required this.txid,
required this.vout,
required this.scriptSig,
required this.scriptSigAsm,
required this.isCoinbase,
required this.sequence,
required this.innerRedeemScriptAsm,
});
Id id = Isar.autoIncrement;
@Index()
late final String walletId;
late final String txid;
late final int vout;
late final String? scriptSig;
late final String? scriptSigAsm;
// TODO: find witness type // is it even used?
// late List<dynamic>? witness;
late final bool? isCoinbase;
late final int? sequence;
late final String? innerRedeemScriptAsm;
final prevOut = IsarLink<Output>();
@Backlink(to: 'inputs')
final transaction = IsarLink<Transaction>();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
part 'output.g.dart';
@Collection()
class Output {
Output({
required this.walletId,
required this.scriptPubKey,
required this.scriptPubKeyAsm,
required this.scriptPubKeyType,
required this.scriptPubKeyAddress,
required this.value,
});
Id id = Isar.autoIncrement;
@Index()
late final String walletId;
late final String? scriptPubKey;
late final String? scriptPubKeyAsm;
late final String? scriptPubKeyType;
late final String scriptPubKeyAddress;
late final int value;
@Backlink(to: 'outputs')
final transaction = IsarLink<Transaction>();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,114 @@
import 'dart:math';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/address/address.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/input.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/output.dart';
part 'transaction.g.dart';
@Collection()
class Transaction {
Transaction({
required this.walletId,
required this.txid,
required this.timestamp,
required this.type,
required this.subType,
required this.amount,
required this.fee,
required this.height,
required this.isCancelled,
required this.isLelantus,
required this.slateId,
required this.otherData,
});
Id id = Isar.autoIncrement;
@Index()
late final String walletId;
@Index(unique: true, composite: [CompositeIndex("walletId")])
late final String txid;
@Index()
late final int timestamp;
@enumerated
late final TransactionType type;
@enumerated
late final TransactionSubType subType;
late final int amount;
late final int fee;
late final int? height;
late final bool isCancelled;
late bool? isLelantus;
late final String? slateId;
late final String? otherData;
@Backlink(to: "transactions")
final address = IsarLink<Address>();
final inputs = IsarLinks<Input>();
final outputs = IsarLinks<Output>();
int getConfirmations(int currentChainHeight) {
if (height == null || height! <= 0) return 0;
return max(0, currentChainHeight - (height! - 1));
}
bool isConfirmed(int currentChainHeight, int minimumConfirms) {
final confirmations = getConfirmations(currentChainHeight);
return confirmations >= minimumConfirms;
}
@override
toString() => "{ "
"id: $id, "
"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}, "
"inputsLength: ${inputs.length}, "
"outputsLength: ${outputs.length}, "
"}";
}
// Used in Isar db and stored there as int indexes so adding/removing values
// in this definition should be done extremely carefully in production
enum TransactionType {
// TODO: add more types before prod release?
outgoing,
incoming,
sentToSelf, // should we keep this?
unknown;
}
// Used in Isar db and stored there as int indexes so adding/removing values
// in this definition should be done extremely carefully in production
enum TransactionSubType {
// TODO: add more types before prod release?
none,
bip47Notification, // bip47 payment code notification transaction flag
mint, // firo specific
join; // firo specific
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,79 @@
import 'dart:math';
import 'package:isar/isar.dart';
part 'utxo.g.dart';
@Collection(accessor: "utxos")
class UTXO {
UTXO({
required this.walletId,
required this.txid,
required this.vout,
required this.value,
required this.name,
required this.isBlocked,
required this.blockedReason,
required this.isCoinbase,
required this.blockHash,
required this.blockHeight,
required this.blockTime,
this.otherData,
});
Id id = Isar.autoIncrement;
@Index()
late final String walletId;
@Index(unique: true, replace: true, composite: [CompositeIndex("walletId")])
late final String txid;
late final int vout;
late final int value;
late final String name;
@Index()
late final bool isBlocked;
late final String? blockedReason;
late final bool isCoinbase;
late final String? blockHash;
late final int? blockHeight;
late final int? blockTime;
late final String? otherData;
int getConfirmations(int currentChainHeight) {
if (blockTime == null || blockHash == null) return 0;
if (blockHeight == null || blockHeight! <= 0) return 0;
return max(0, currentChainHeight - (blockHeight! - 1));
}
bool isConfirmed(int currentChainHeight, int minimumConfirms) {
final confirmations = getConfirmations(currentChainHeight);
return confirmations >= minimumConfirms;
}
@override
String toString() => "{ "
"id: $id, "
"walletId: $walletId, "
"txid: $txid, "
"vout: $vout, "
"value: $value, "
"name: $name, "
"isBlocked: $isBlocked, "
"blockedReason: $blockedReason, "
"isCoinbase: $isCoinbase, "
"blockHash: $blockHash, "
"blockHeight: $blockHeight, "
"blockTime: $blockTime, "
"}";
}

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ part of 'encrypted_string_value.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, join_return_with_assignment, avoid_js_rounded_ints, prefer_final_locals
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
extension GetEncryptedStringValueCollection on Isar {
IsarCollection<EncryptedStringValue> get encryptedStringValues =>
@ -30,12 +30,9 @@ const EncryptedStringValueSchema = CollectionSchema(
)
},
estimateSize: _encryptedStringValueEstimateSize,
serializeNative: _encryptedStringValueSerializeNative,
deserializeNative: _encryptedStringValueDeserializeNative,
deserializePropNative: _encryptedStringValueDeserializePropNative,
serializeWeb: _encryptedStringValueSerializeWeb,
deserializeWeb: _encryptedStringValueDeserializeWeb,
deserializePropWeb: _encryptedStringValueDeserializePropWeb,
serialize: _encryptedStringValueSerialize,
deserialize: _encryptedStringValueDeserialize,
deserializeProp: _encryptedStringValueDeserializeProp,
idName: r'id',
indexes: {
r'key': IndexSchema(
@ -57,7 +54,7 @@ const EncryptedStringValueSchema = CollectionSchema(
getId: _encryptedStringValueGetId,
getLinks: _encryptedStringValueGetLinks,
attach: _encryptedStringValueAttach,
version: 5,
version: '3.0.5',
);
int _encryptedStringValueEstimateSize(
@ -71,20 +68,19 @@ int _encryptedStringValueEstimateSize(
return bytesCount;
}
int _encryptedStringValueSerializeNative(
void _encryptedStringValueSerialize(
EncryptedStringValue object,
IsarBinaryWriter writer,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeString(offsets[0], object.key);
writer.writeString(offsets[1], object.value);
return writer.usedBytes;
}
EncryptedStringValue _encryptedStringValueDeserializeNative(
int id,
IsarBinaryReader reader,
EncryptedStringValue _encryptedStringValueDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
@ -95,9 +91,8 @@ EncryptedStringValue _encryptedStringValueDeserializeNative(
return object;
}
P _encryptedStringValueDeserializePropNative<P>(
Id id,
IsarBinaryReader reader,
P _encryptedStringValueDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
@ -112,33 +107,8 @@ P _encryptedStringValueDeserializePropNative<P>(
}
}
Object _encryptedStringValueSerializeWeb(
IsarCollection<EncryptedStringValue> collection,
EncryptedStringValue object) {
/*final jsObj = IsarNative.newJsObject();*/ throw UnimplementedError();
}
EncryptedStringValue _encryptedStringValueDeserializeWeb(
IsarCollection<EncryptedStringValue> collection, Object jsObj) {
/*final object = EncryptedStringValue();object.id = IsarNative.jsObjectGet(jsObj, r'id') ?? (double.negativeInfinity as int);object.key = IsarNative.jsObjectGet(jsObj, r'key') ?? '';object.value = IsarNative.jsObjectGet(jsObj, r'value') ?? '';*/
//return object;
throw UnimplementedError();
}
P _encryptedStringValueDeserializePropWeb<P>(
Object jsObj, String propertyName) {
switch (propertyName) {
default:
throw IsarError('Illegal propertyName');
}
}
int? _encryptedStringValueGetId(EncryptedStringValue object) {
if (object.id == Isar.autoIncrement) {
return null;
} else {
return object.id;
}
Id _encryptedStringValueGetId(EncryptedStringValue object) {
return object.id;
}
List<IsarLinkBase<dynamic>> _encryptedStringValueGetLinks(
@ -188,19 +158,19 @@ extension EncryptedStringValueByIndex on IsarCollection<EncryptedStringValue> {
return deleteAllByIndexSync(r'key', values);
}
Future<int> putByKey(EncryptedStringValue object) {
Future<Id> putByKey(EncryptedStringValue object) {
return putByIndex(r'key', object);
}
int putByKeySync(EncryptedStringValue object, {bool saveLinks = true}) {
Id putByKeySync(EncryptedStringValue object, {bool saveLinks = true}) {
return putByIndexSync(r'key', object, saveLinks: saveLinks);
}
Future<List<int>> putAllByKey(List<EncryptedStringValue> objects) {
Future<List<Id>> putAllByKey(List<EncryptedStringValue> objects) {
return putAllByIndex(r'key', objects);
}
List<int> putAllByKeySync(List<EncryptedStringValue> objects,
List<Id> putAllByKeySync(List<EncryptedStringValue> objects,
{bool saveLinks = true}) {
return putAllByIndexSync(r'key', objects, saveLinks: saveLinks);
}
@ -219,7 +189,7 @@ extension EncryptedStringValueQueryWhereSort
extension EncryptedStringValueQueryWhere
on QueryBuilder<EncryptedStringValue, EncryptedStringValue, QWhereClause> {
QueryBuilder<EncryptedStringValue, EncryptedStringValue, QAfterWhereClause>
idEqualTo(int id) {
idEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: id,
@ -229,7 +199,7 @@ extension EncryptedStringValueQueryWhere
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue, QAfterWhereClause>
idNotEqualTo(int id) {
idNotEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
@ -252,7 +222,7 @@ extension EncryptedStringValueQueryWhere
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue, QAfterWhereClause>
idGreaterThan(int id, {bool include = false}) {
idGreaterThan(Id id, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: include),
@ -261,7 +231,7 @@ extension EncryptedStringValueQueryWhere
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue, QAfterWhereClause>
idLessThan(int id, {bool include = false}) {
idLessThan(Id id, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: include),
@ -271,8 +241,8 @@ extension EncryptedStringValueQueryWhere
QueryBuilder<EncryptedStringValue, EncryptedStringValue, QAfterWhereClause>
idBetween(
int lowerId,
int upperId, {
Id lowerId,
Id upperId, {
bool includeLower = true,
bool includeUpper = true,
}) {
@ -335,7 +305,7 @@ extension EncryptedStringValueQueryWhere
extension EncryptedStringValueQueryFilter on QueryBuilder<EncryptedStringValue,
EncryptedStringValue, QFilterCondition> {
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> idEqualTo(int value) {
QAfterFilterCondition> idEqualTo(Id value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'id',
@ -346,7 +316,7 @@ extension EncryptedStringValueQueryFilter on QueryBuilder<EncryptedStringValue,
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> idGreaterThan(
int value, {
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
@ -360,7 +330,7 @@ extension EncryptedStringValueQueryFilter on QueryBuilder<EncryptedStringValue,
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> idLessThan(
int value, {
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
@ -374,8 +344,8 @@ extension EncryptedStringValueQueryFilter on QueryBuilder<EncryptedStringValue,
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> idBetween(
int lower,
int upper, {
Id lower,
Id upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
@ -508,6 +478,26 @@ extension EncryptedStringValueQueryFilter on QueryBuilder<EncryptedStringValue,
});
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> keyIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'key',
value: '',
));
});
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> keyIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'key',
value: '',
));
});
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> valueEqualTo(
String value, {
@ -625,6 +615,26 @@ extension EncryptedStringValueQueryFilter on QueryBuilder<EncryptedStringValue,
));
});
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> valueIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'value',
value: '',
));
});
}
QueryBuilder<EncryptedStringValue, EncryptedStringValue,
QAfterFilterCondition> valueIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'value',
value: '',
));
});
}
}
extension EncryptedStringValueQueryObject on QueryBuilder<EncryptedStringValue,

View file

@ -0,0 +1,7 @@
export 'address/address.dart';
export 'blockchain_data/input.dart';
export 'blockchain_data/output.dart';
export 'blockchain_data/transaction.dart';
export 'blockchain_data/utxo.dart';
export 'log.dart';
export 'transaction_note.dart';

View file

@ -13,6 +13,7 @@ class Log {
@Index()
late int timestampInMillisUTC;
@Enumerated(EnumType.name)
late LogLevel logLevel;
@override

View file

@ -7,7 +7,7 @@ part of 'log.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, join_return_with_assignment, avoid_js_rounded_ints, prefer_final_locals
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
extension GetLogCollection on Isar {
IsarCollection<Log> get logs => this.collection();
@ -21,6 +21,7 @@ const LogSchema = CollectionSchema(
id: 0,
name: r'logLevel',
type: IsarType.string,
enumMap: _LoglogLevelEnumValueMap,
),
r'message': PropertySchema(
id: 1,
@ -34,12 +35,9 @@ const LogSchema = CollectionSchema(
)
},
estimateSize: _logEstimateSize,
serializeNative: _logSerializeNative,
deserializeNative: _logDeserializeNative,
deserializePropNative: _logDeserializePropNative,
serializeWeb: _logSerializeWeb,
deserializeWeb: _logDeserializeWeb,
deserializePropWeb: _logDeserializePropWeb,
serialize: _logSerialize,
deserialize: _logDeserialize,
deserializeProp: _logDeserializeProp,
idName: r'id',
indexes: {
r'timestampInMillisUTC': IndexSchema(
@ -61,7 +59,7 @@ const LogSchema = CollectionSchema(
getId: _logGetId,
getLinks: _logGetLinks,
attach: _logAttach,
version: 5,
version: '3.0.5',
);
int _logEstimateSize(
@ -70,49 +68,48 @@ int _logEstimateSize(
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
bytesCount += 3 + object.logLevel.value.length * 3;
bytesCount += 3 + object.logLevel.name.length * 3;
bytesCount += 3 + object.message.length * 3;
return bytesCount;
}
int _logSerializeNative(
void _logSerialize(
Log object,
IsarBinaryWriter writer,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeString(offsets[0], object.logLevel.value);
writer.writeString(offsets[0], object.logLevel.name);
writer.writeString(offsets[1], object.message);
writer.writeLong(offsets[2], object.timestampInMillisUTC);
return writer.usedBytes;
}
Log _logDeserializeNative(
int id,
IsarBinaryReader reader,
Log _logDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = Log();
object.id = id;
object.logLevel =
_LogLogLevelMap[reader.readStringOrNull(offsets[0])] ?? LogLevel.Info;
_LoglogLevelValueEnumMap[reader.readStringOrNull(offsets[0])] ??
LogLevel.Info;
object.message = reader.readString(offsets[1]);
object.timestampInMillisUTC = reader.readLong(offsets[2]);
return object;
}
P _logDeserializePropNative<P>(
Id id,
IsarBinaryReader reader,
P _logDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (_LogLogLevelMap[reader.readStringOrNull(offset)] ?? LogLevel.Info)
as P;
return (_LoglogLevelValueEnumMap[reader.readStringOrNull(offset)] ??
LogLevel.Info) as P;
case 1:
return (reader.readString(offset)) as P;
case 2:
@ -122,36 +119,21 @@ P _logDeserializePropNative<P>(
}
}
Object _logSerializeWeb(IsarCollection<Log> collection, Log object) {
/*final jsObj = IsarNative.newJsObject();*/ throw UnimplementedError();
}
Log _logDeserializeWeb(IsarCollection<Log> collection, Object jsObj) {
/*final object = Log();object.id = IsarNative.jsObjectGet(jsObj, r'id') ?? (double.negativeInfinity as int);object.logLevel = IsarNative.jsObjectGet(jsObj, r'logLevel') ?? LogLevel.Info;object.message = IsarNative.jsObjectGet(jsObj, r'message') ?? '';object.timestampInMillisUTC = IsarNative.jsObjectGet(jsObj, r'timestampInMillisUTC') ?? (double.negativeInfinity as int);*/
//return object;
throw UnimplementedError();
}
P _logDeserializePropWeb<P>(Object jsObj, String propertyName) {
switch (propertyName) {
default:
throw IsarError('Illegal propertyName');
}
}
final _LogLogLevelMap = {
LogLevel.Info.value: LogLevel.Info,
LogLevel.Warning.value: LogLevel.Warning,
LogLevel.Error.value: LogLevel.Error,
LogLevel.Fatal.value: LogLevel.Fatal,
const _LoglogLevelEnumValueMap = {
r'Info': r'Info',
r'Warning': r'Warning',
r'Error': r'Error',
r'Fatal': r'Fatal',
};
const _LoglogLevelValueEnumMap = {
r'Info': LogLevel.Info,
r'Warning': LogLevel.Warning,
r'Error': LogLevel.Error,
r'Fatal': LogLevel.Fatal,
};
int? _logGetId(Log object) {
if (object.id == Isar.autoIncrement) {
return null;
} else {
return object.id;
}
Id _logGetId(Log object) {
return object.id;
}
List<IsarLinkBase<dynamic>> _logGetLinks(Log object) {
@ -179,7 +161,7 @@ extension LogQueryWhereSort on QueryBuilder<Log, Log, QWhere> {
}
extension LogQueryWhere on QueryBuilder<Log, Log, QWhereClause> {
QueryBuilder<Log, Log, QAfterWhereClause> idEqualTo(int id) {
QueryBuilder<Log, Log, QAfterWhereClause> idEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: id,
@ -188,7 +170,7 @@ extension LogQueryWhere on QueryBuilder<Log, Log, QWhereClause> {
});
}
QueryBuilder<Log, Log, QAfterWhereClause> idNotEqualTo(int id) {
QueryBuilder<Log, Log, QAfterWhereClause> idNotEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
@ -210,7 +192,7 @@ extension LogQueryWhere on QueryBuilder<Log, Log, QWhereClause> {
});
}
QueryBuilder<Log, Log, QAfterWhereClause> idGreaterThan(int id,
QueryBuilder<Log, Log, QAfterWhereClause> idGreaterThan(Id id,
{bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
@ -219,7 +201,7 @@ extension LogQueryWhere on QueryBuilder<Log, Log, QWhereClause> {
});
}
QueryBuilder<Log, Log, QAfterWhereClause> idLessThan(int id,
QueryBuilder<Log, Log, QAfterWhereClause> idLessThan(Id id,
{bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
@ -229,8 +211,8 @@ extension LogQueryWhere on QueryBuilder<Log, Log, QWhereClause> {
}
QueryBuilder<Log, Log, QAfterWhereClause> idBetween(
int lowerId,
int upperId, {
Id lowerId,
Id upperId, {
bool includeLower = true,
bool includeUpper = true,
}) {
@ -336,7 +318,7 @@ extension LogQueryWhere on QueryBuilder<Log, Log, QWhereClause> {
}
extension LogQueryFilter on QueryBuilder<Log, Log, QFilterCondition> {
QueryBuilder<Log, Log, QAfterFilterCondition> idEqualTo(int value) {
QueryBuilder<Log, Log, QAfterFilterCondition> idEqualTo(Id value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'id',
@ -346,7 +328,7 @@ extension LogQueryFilter on QueryBuilder<Log, Log, QFilterCondition> {
}
QueryBuilder<Log, Log, QAfterFilterCondition> idGreaterThan(
int value, {
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
@ -359,7 +341,7 @@ extension LogQueryFilter on QueryBuilder<Log, Log, QFilterCondition> {
}
QueryBuilder<Log, Log, QAfterFilterCondition> idLessThan(
int value, {
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
@ -372,8 +354,8 @@ extension LogQueryFilter on QueryBuilder<Log, Log, QFilterCondition> {
}
QueryBuilder<Log, Log, QAfterFilterCondition> idBetween(
int lower,
int upper, {
Id lower,
Id upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
@ -498,6 +480,24 @@ extension LogQueryFilter on QueryBuilder<Log, Log, QFilterCondition> {
});
}
QueryBuilder<Log, Log, QAfterFilterCondition> logLevelIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'logLevel',
value: '',
));
});
}
QueryBuilder<Log, Log, QAfterFilterCondition> logLevelIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'logLevel',
value: '',
));
});
}
QueryBuilder<Log, Log, QAfterFilterCondition> messageEqualTo(
String value, {
bool caseSensitive = true,
@ -608,6 +608,24 @@ extension LogQueryFilter on QueryBuilder<Log, Log, QFilterCondition> {
});
}
QueryBuilder<Log, Log, QAfterFilterCondition> messageIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'message',
value: '',
));
});
}
QueryBuilder<Log, Log, QAfterFilterCondition> messageIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'message',
value: '',
));
});
}
QueryBuilder<Log, Log, QAfterFilterCondition> timestampInMillisUTCEqualTo(
int value) {
return QueryBuilder.apply(this, (query) {

View file

@ -0,0 +1,22 @@
import 'package:isar/isar.dart';
part 'transaction_note.g.dart';
@Collection()
class TransactionNote {
TransactionNote({
required this.walletId,
required this.txid,
required this.value,
});
Id id = Isar.autoIncrement;
@Index()
late String walletId;
@Index(unique: true, composite: [CompositeIndex("walletId")])
late String txid;
late String value;
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
@ -160,8 +161,9 @@ class _VerifyRecoveryPhraseViewState
result.insert(random.nextInt(wordsToShow), chosenWord);
//todo: this prints sensitive info
debugPrint("Mnemonic game correct word: $chosenWord");
if (kDebugMode) {
print("Mnemonic game correct word: $chosenWord");
}
return Tuple2(result, chosenWord);
}

View file

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
@ -15,7 +15,6 @@ import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
@ -28,6 +27,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/widgets/transaction_card.dart';
import 'package:tuple/tuple.dart';
import '../../../db/main_db.dart';
class ContactDetailsView extends ConsumerStatefulWidget {
const ContactDetailsView({
Key? key,
@ -50,15 +51,6 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
List<Tuple2<String, Transaction>> _cachedTransactions = [];
bool _contactHasAddress(String address, Contact contact) {
for (final entry in contact.addresses) {
if (entry.address == address) {
return true;
}
}
return false;
}
Future<List<Tuple2<String, Transaction>>> _filteredTransactionsByContact(
List<Manager> managers,
) async {
@ -69,18 +61,18 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
List<Tuple2<String, Transaction>> result = [];
for (final manager in managers) {
final transactions = (await manager.transactionData)
.getAllTransactions()
.values
.toList()
.where((e) => _contactHasAddress(e.address, contact));
final transactions = await MainDB.instance
.getTransactions(manager.walletId)
.filter()
.anyOf(contact.addresses.map((e) => e.address),
(q, String e) => q.address((q) => q.valueEqualTo(e)))
.sortByTimestampDesc()
.findAll();
for (final tx in transactions) {
result.add(Tuple2(manager.walletId, tx));
}
}
// sort by date
result.sort((a, b) => b.item2.timestamp - a.item2.timestamp);
return result;
}

View file

@ -2,6 +2,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
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';
@ -12,6 +14,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/trade_card.dart';
import 'package:tuple/tuple.dart';
import '../../db/main_db.dart';
class ExchangeView extends ConsumerStatefulWidget {
const ExchangeView({Key? key}) : super(key: key);
@ -129,10 +133,11 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
// TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
final txData = await manager.transactionData;
final tx = txData.getAllTransactions()[txid];
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
if (mounted) {
unawaited(Navigator.of(context).pushNamed(

View file

@ -438,8 +438,10 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
style: STextStyles.itemSubtitle(context),
),
FutureBuilder(
future: (manager.wallet as FiroWallet)
.availablePrivateBalance(),
// TODO redo this widget now that its not actually a future
future: Future(() =>
(manager.wallet as FiroWallet)
.availablePrivateBalance()),
builder: (builderContext,
AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
@ -524,8 +526,10 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
style: STextStyles.itemSubtitle(context),
),
FutureBuilder(
future: (manager.wallet as FiroWallet)
.availablePublicBalance(),
// TODO redo this widget now that its not actually a future
future: Future(() =>
(manager.wallet as FiroWallet)
.availablePublicBalance()),
builder: (builderContext,
AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
@ -634,7 +638,8 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
),
if (!isFiro)
FutureBuilder(
future: manager.totalBalance,
// TODO redo this widget now that its not actually a future
future: Future(() => manager.balance.getTotal()),
builder:
(builderContext, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==

View file

@ -7,7 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart';
import 'package:stackwallet/pages/exchange_view/send_from_view.dart';
@ -23,7 +23,6 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';

View file

@ -485,22 +485,22 @@ class _SendViewState extends ConsumerState<SendView> {
coin == Coin.firoTestNet)
const Spacer(),
FutureBuilder(
// TODO redo this widget now that its not actually a future
future: (coin != Coin.firo &&
coin != Coin.firoTestNet)
? ref.watch(provider.select(
(value) => value.availableBalance))
: ref
.watch(
publicPrivateBalanceStateProvider
.state)
.state ==
? Future(() => ref.watch(
provider.select((value) =>
value.balance.getSpendable())))
: ref.watch(publicPrivateBalanceStateProvider.state).state ==
"Private"
? (ref.watch(provider).wallet
as FiroWallet)
.availablePrivateBalance()
: (ref.watch(provider).wallet
as FiroWallet)
.availablePublicBalance(),
? Future(() => (ref
.watch(provider)
.wallet as FiroWallet)
.availablePrivateBalance())
: Future(() => (ref
.watch(provider)
.wallet as FiroWallet)
.availablePublicBalance()),
builder:
(_, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
@ -1085,9 +1085,10 @@ class _SendViewState extends ConsumerState<SendView> {
.decimalPlacesForCoin(coin));
}
} else {
cryptoAmountController.text = (await ref
cryptoAmountController.text = (ref
.read(provider)
.availableBalance)
.balance
.getSpendable())
.toStringAsFixed(
Constants.decimalPlacesForCoin(
coin));
@ -1523,43 +1524,43 @@ class _SendViewState extends ConsumerState<SendView> {
.read(walletsChangeNotifierProvider)
.getManager(walletId);
// TODO: remove the need for this!!
final bool isOwnAddress =
await manager.isOwnAddress(_address!);
if (isOwnAddress && coin != Coin.dogecoinTestNet) {
await showDialog<dynamic>(
context: context,
useSafeArea: false,
barrierDismissible: true,
builder: (context) {
return StackDialog(
title: "Transaction failed",
message:
"Sending to self is currently disabled",
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(
context),
child: Text(
"Ok",
style: STextStyles.button(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.accentColorDark),
),
onPressed: () {
Navigator.of(context).pop();
},
),
);
},
);
return;
}
// // TODO: remove the need for this!!
// final bool isOwnAddress =
// await manager.isOwnAddress(_address!);
// if (isOwnAddress && coin != Coin.dogecoinTestNet) {
// await showDialog<dynamic>(
// context: context,
// useSafeArea: false,
// barrierDismissible: true,
// builder: (context) {
// return StackDialog(
// title: "Transaction failed",
// message:
// "Sending to self is currently disabled",
// rightButton: TextButton(
// style: Theme.of(context)
// .extension<StackColors>()!
// .getSecondaryEnabledButtonColor(
// context),
// child: Text(
// "Ok",
// style: STextStyles.button(
// context)
// .copyWith(
// color: Theme.of(context)
// .extension<
// StackColors>()!
// .accentColorDark),
// ),
// onPressed: () {
// Navigator.of(context).pop();
// },
// ),
// );
// },
// );
// return;
// }
final amount =
Format.decimalAmountToSatoshis(
@ -1575,22 +1576,20 @@ class _SendViewState extends ConsumerState<SendView> {
"Private") {
availableBalance =
Format.decimalAmountToSatoshis(
await (manager.wallet
as FiroWallet)
(manager.wallet as FiroWallet)
.availablePrivateBalance(),
coin);
} else {
availableBalance =
Format.decimalAmountToSatoshis(
await (manager.wallet
as FiroWallet)
(manager.wallet as FiroWallet)
.availablePublicBalance(),
coin);
}
} else {
availableBalance =
Format.decimalAmountToSatoshis(
await manager.availableBalance,
manager.balance.getSpendable(),
coin);
}

View file

@ -154,7 +154,9 @@ class _FiroBalanceSelectionSheetState
width: 2,
),
FutureBuilder(
future: firoWallet.availablePrivateBalance(),
// TODO redo this widget now that its not actually a future
future: Future(
() => firoWallet.availablePrivateBalance()),
builder:
(context, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
@ -244,7 +246,9 @@ class _FiroBalanceSelectionSheetState
width: 2,
),
FutureBuilder(
future: firoWallet.availablePublicBalance(),
// TODO redo this widget now that its not actually a future
future: Future(
() => firoWallet.availablePublicBalance()),
builder:
(context, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==

View file

@ -145,7 +145,8 @@ class WalletSyncingOptionsView extends ConsumerWidget {
height: 2,
),
FutureBuilder(
future: manager.totalBalance,
future: Future(
() => manager.balance.getTotal()),
builder: (builderContext,
AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==

View file

@ -2,9 +2,10 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/no_transactions_found.dart';
import 'package:stackwallet/providers/blockchain/dogecoin/current_height_provider.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/route_generator.dart';
@ -37,19 +38,10 @@ class TransactionsList extends ConsumerStatefulWidget {
class _TransactionsListState extends ConsumerState<TransactionsList> {
//
bool _hasLoaded = false;
Map<String, Transaction> _transactions = {};
List<Transaction> _transactions2 = [];
late final ChangeNotifierProvider<Manager> managerProvider;
void updateTransactions(TransactionData newData) {
_transactions = {};
final newTransactions =
newData.txChunks.expand((element) => element.transactions);
for (final tx in newTransactions) {
_transactions[tx.txid] = tx;
}
}
BorderRadius get _borderRadiusFirst {
return BorderRadius.only(
topLeft: Radius.circular(
@ -73,12 +65,15 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
}
Widget itemBuilder(
BuildContext context, Transaction tx, BorderRadius? radius) {
BuildContext context,
Transaction tx,
BorderRadius? radius,
) {
final matchingTrades = ref
.read(tradesServiceProvider)
.trades
.where((e) => e.payInTxid == tx.txid || e.payOutTxid == tx.txid);
if (tx.txType == "Sent" && matchingTrades.isNotEmpty) {
if (tx.type == TransactionType.outgoing && matchingTrades.isNotEmpty) {
final trade = matchingTrades.first;
return Container(
decoration: BoxDecoration(
@ -90,13 +85,16 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
children: [
TransactionCard(
// this may mess with combined firo transactions
key: Key(tx.toString()), //
key: Key(tx.txid + tx.type.name + tx.address.value.toString()), //
transaction: tx,
walletId: widget.walletId,
),
TradeCard(
// this may mess with combined firo transactions
key: Key(tx.toString() + trade.uuid), //
key: Key(tx.txid +
tx.type.name +
tx.address.value.toString() +
trade.uuid), //
trade: trade,
onTap: () async {
if (Util.isDesktop) {
@ -182,7 +180,7 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
),
child: TransactionCard(
// this may mess with combined firo transactions
key: Key(tx.toString()), //
key: Key(tx.txid + tx.type.name + tx.address.value.toString()), //
transaction: tx,
walletId: widget.walletId,
),
@ -190,6 +188,13 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
}
}
void updateHeightProvider(Manager manager) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
ref.read(currentHeightProvider(manager.coin).state).state =
manager.currentHeight;
});
}
@override
void initState() {
managerProvider = widget.managerProvider;
@ -202,13 +207,16 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
// .watch(walletsChangeNotifierProvider)
// .getManagerProvider(widget.walletId);
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(widget.walletId)));
updateHeightProvider(manager);
return FutureBuilder(
future:
ref.watch(managerProvider.select((value) => value.transactionData)),
builder: (fbContext, AsyncSnapshot<TransactionData> snapshot) {
future: manager.transactions,
builder: (fbContext, AsyncSnapshot<List<Transaction>> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
updateTransactions(snapshot.data!);
_transactions2 = snapshot.data!;
_hasLoaded = true;
}
if (!_hasLoaded) {
@ -227,11 +235,10 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
],
);
}
if (_transactions.isEmpty) {
if (_transactions2.isEmpty) {
return const NoTransActionsFound();
} else {
final list = _transactions.values.toList(growable: false);
list.sort((a, b) => b.timestamp - a.timestamp);
_transactions2.sort((a, b) => b.timestamp - a.timestamp);
return RefreshIndicator(
onRefresh: () async {
//todo: check if print needed
@ -247,16 +254,16 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
? ListView.separated(
itemBuilder: (context, index) {
BorderRadius? radius;
if (list.length == 1) {
if (_transactions2.length == 1) {
radius = BorderRadius.circular(
Constants.size.circularBorderRadius,
);
} else if (index == list.length - 1) {
} else if (index == _transactions2.length - 1) {
radius = _borderRadiusLast;
} else if (index == 0) {
radius = _borderRadiusFirst;
}
final tx = list[index];
final tx = _transactions2[index];
return itemBuilder(context, tx, radius);
},
separatorBuilder: (context, index) {
@ -268,22 +275,22 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
.background,
);
},
itemCount: list.length,
itemCount: _transactions2.length,
)
: ListView.builder(
itemCount: list.length,
itemCount: _transactions2.length,
itemBuilder: (context, index) {
BorderRadius? radius;
if (list.length == 1) {
if (_transactions2.length == 1) {
radius = BorderRadius.circular(
Constants.size.circularBorderRadius,
);
} else if (index == list.length - 1) {
} else if (index == _transactions2.length - 1) {
radius = _borderRadiusLast;
} else if (index == 0) {
radius = _borderRadiusFirst;
}
final tx = list[index];
final tx = _transactions2[index];
return itemBuilder(context, tx, radius);
},
),

View file

@ -1,17 +1,26 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
class TxIcon extends StatelessWidget {
const TxIcon({Key? key, required this.transaction}) : super(key: key);
const TxIcon({
Key? key,
required this.transaction,
required this.currentHeight,
required this.coin,
}) : super(key: key);
final Transaction transaction;
final int currentHeight;
final Coin coin;
static const Size size = Size(32, 32);
String _getAssetName(
bool isCancelled, bool isReceived, bool isPending, BuildContext context) {
if (!isReceived && transaction.subType == "mint") {
if (!isReceived && transaction.subType == TransactionSubType.mint) {
if (isCancelled) {
return Assets.svg.anonymizeFailed;
}
@ -42,7 +51,7 @@ class TxIcon extends StatelessWidget {
@override
Widget build(BuildContext context) {
final txIsReceived = transaction.txType == "Received";
final txIsReceived = transaction.type == TransactionType.incoming;
return SizedBox(
width: size.width,
@ -52,7 +61,10 @@ class TxIcon extends StatelessWidget {
_getAssetName(
transaction.isCancelled,
txIsReceived,
!transaction.confirmedStatus,
!transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
),
context,
),
width: size.width,

View file

@ -32,13 +32,14 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)))
.wallet as FiroWallet;
totalBalanceFuture = firoWallet.availablePublicBalance();
availableBalanceFuture = firoWallet.availablePrivateBalance();
totalBalanceFuture = Future(() => firoWallet.balance.getSpendable());
availableBalanceFuture =
Future(() => firoWallet.balancePrivate.getSpendable());
} else {
final wallet = ref.watch(walletsChangeNotifierProvider
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
totalBalanceFuture = wallet.totalBalance;
availableBalanceFuture = wallet.availableBalance;
totalBalanceFuture = Future(() => manager.balance.getTotal());
availableBalanceFuture = Future(() => manager.balance.getSpendable());
}
return Container(

View file

@ -79,14 +79,16 @@ class _WalletSummaryInfoState extends State<WalletSummaryInfo> {
final firoWallet =
ref.watch(managerProvider.select((value) => value.wallet))
as FiroWallet;
totalBalanceFuture = firoWallet.availablePublicBalance();
availableBalanceFuture = firoWallet.availablePrivateBalance();
totalBalanceFuture =
Future(() => firoWallet.balance.getSpendable());
availableBalanceFuture =
Future(() => firoWallet.balancePrivate.getSpendable());
} else {
totalBalanceFuture = ref.watch(
managerProvider.select((value) => value.totalBalance));
availableBalanceFuture = ref.watch(
managerProvider.select((value) => value.availableBalance));
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
totalBalanceFuture = Future(() => manager.balance.getTotal());
availableBalanceFuture =
Future(() => manager.balance.getSpendable());
}
final locale = ref.watch(localeServiceChangeNotifierProvider

View file

@ -4,12 +4,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/transaction_filter.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart';
import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_search_filter_view.dart';
import 'package:stackwallet/providers/blockchain/dogecoin/current_height_provider.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
@ -89,11 +90,15 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
return false;
}
if (filter.received && !filter.sent && tx.txType == "Sent") {
if (filter.received &&
!filter.sent &&
tx.type == TransactionType.outgoing) {
return false;
}
if (filter.sent && !filter.received && tx.txType == "Received") {
if (filter.sent &&
!filter.received &&
tx.type == TransactionType.incoming) {
return false;
}
@ -131,7 +136,8 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
.isNotEmpty;
// check if address contains
contains |= tx.address.toLowerCase().contains(keyword);
contains |=
tx.address.value?.value.toLowerCase().contains(keyword) ?? false;
// check if note contains
contains |= notes[tx.txid] != null &&
@ -141,11 +147,10 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
contains |= tx.txid.toLowerCase().contains(keyword);
// check if subType contains
contains |=
tx.subType.isNotEmpty && tx.subType.toLowerCase().contains(keyword);
contains |= tx.subType.name.toLowerCase().contains(keyword);
// check if txType contains
contains |= tx.txType.toLowerCase().contains(keyword);
contains |= tx.type.name.toLowerCase().contains(keyword);
// check if date contains
contains |=
@ -454,17 +459,13 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
// debugPrint("Consumer build called");
return FutureBuilder(
future: ref.watch(managerProvider
.select((value) => value.transactionData)),
builder: (_, AsyncSnapshot<TransactionData> snapshot) {
future: ref.watch(
managerProvider.select((value) => value.transactions)),
builder: (_, AsyncSnapshot<List<Transaction>> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final filtered = filter(
transactions: snapshot.data!
.getAllTransactions()
.values
.toList(),
filter: criteria);
transactions: snapshot.data!, filter: criteria);
final searched = search(_searchString, filtered);
@ -787,33 +788,33 @@ class _DesktopTransactionCardRowState
late final Transaction _transaction;
late final String walletId;
String whatIsIt(String type, Coin coin) {
String whatIsIt(TransactionType type, Coin coin, int height) {
if (coin == Coin.epicCash && _transaction.slateId == null) {
return "Restored Funds";
}
if (_transaction.subType == "mint") {
if (_transaction.confirmedStatus) {
if (_transaction.subType == TransactionSubType.mint) {
if (_transaction.isConfirmed(height, coin.requiredConfirmations)) {
return "Anonymized";
} else {
return "Anonymizing";
}
}
if (type == "Received") {
if (_transaction.confirmedStatus) {
if (type == TransactionType.incoming) {
if (_transaction.isConfirmed(height, coin.requiredConfirmations)) {
return "Received";
} else {
return "Receiving";
}
} else if (type == "Sent") {
if (_transaction.confirmedStatus) {
} else if (type == TransactionType.outgoing) {
if (_transaction.isConfirmed(height, coin.requiredConfirmations)) {
return "Sent";
} else {
return "Sending";
}
} else {
return type;
return type.name;
}
}
@ -843,15 +844,17 @@ class _DesktopTransactionCardRowState
late final String prefix;
if (Util.isDesktop) {
if (_transaction.txType == "Sent") {
if (_transaction.type == TransactionType.outgoing) {
prefix = "-";
} else if (_transaction.txType == "Received") {
} else if (_transaction.type == TransactionType.incoming) {
prefix = "+";
}
} else {
prefix = "";
}
final currentHeight = ref.watch(currentHeightProvider(coin).state).state;
return Material(
color: Theme.of(context).extension<StackColors>()!.popupBG,
elevation: 0,
@ -911,7 +914,11 @@ class _DesktopTransactionCardRowState
),
child: Row(
children: [
TxIcon(transaction: _transaction),
TxIcon(
transaction: _transaction,
currentHeight: currentHeight,
coin: coin,
),
const SizedBox(
width: 12,
),
@ -920,7 +927,11 @@ class _DesktopTransactionCardRowState
child: Text(
_transaction.isCancelled
? "Cancelled"
: whatIsIt(_transaction.txType, coin),
: whatIsIt(
_transaction.type,
coin,
currentHeight,
),
style:
STextStyles.desktopTextExtraExtraSmall(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark,

View file

@ -5,12 +5,13 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/models.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
import 'package:stackwallet/pages/wallet_view/transaction_views/dialogs/cancelling_transaction_progress_dialog.dart';
import 'package:stackwallet/pages/wallet_view/transaction_views/edit_note_view.dart';
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
import 'package:stackwallet/providers/blockchain/dogecoin/current_height_provider.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
@ -19,7 +20,6 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/block_explorers.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -80,13 +80,13 @@ class _TransactionDetailsViewState
coin = widget.coin;
amount = Format.satoshisToAmount(_transaction.amount, coin: coin);
fee = Format.satoshisToAmount(_transaction.fees, coin: coin);
fee = Format.satoshisToAmount(_transaction.fee, coin: coin);
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
_transaction.subType == "mint") {
_transaction.subType == TransactionSubType.mint) {
amountPrefix = "";
} else {
amountPrefix = _transaction.txType.toLowerCase() == "sent" ? "-" : "+";
amountPrefix = _transaction.type == TransactionType.outgoing ? "-" : "+";
}
// if (coin == Coin.firo || coin == Coin.firoTestNet) {
@ -102,10 +102,10 @@ class _TransactionDetailsViewState
super.dispose();
}
String whatIsIt(String type) {
String whatIsIt(TransactionType type, int height) {
if (coin == Coin.firo || coin == Coin.firoTestNet) {
if (_transaction.subType == "mint") {
if (_transaction.confirmedStatus) {
if (_transaction.subType == TransactionSubType.mint) {
if (_transaction.isConfirmed(height, coin.requiredConfirmations)) {
return "Minted";
} else {
return "Minting";
@ -113,23 +113,23 @@ class _TransactionDetailsViewState
}
}
if (type == "Received") {
if (type == TransactionType.incoming) {
// if (_transaction.isMinting) {
// return "Minting";
// } else
if (_transaction.confirmedStatus) {
if (_transaction.isConfirmed(height, coin.requiredConfirmations)) {
return "Received";
} else {
return "Receiving";
}
} else if (type == "Sent") {
if (_transaction.confirmedStatus) {
} else if (type == TransactionType.outgoing) {
if (_transaction.isConfirmed(height, coin.requiredConfirmations)) {
return "Sent";
} else {
return "Sending";
}
} else {
return type;
return type.name;
}
}
@ -298,6 +298,8 @@ class _TransactionDetailsViewState
@override
Widget build(BuildContext context) {
final currentHeight = ref.watch(currentHeightProvider(coin).state).state;
return ConditionalParent(
condition: !isDesktop,
builder: (child) => Background(
@ -403,6 +405,8 @@ class _TransactionDetailsViewState
children: [
TxIcon(
transaction: _transaction,
currentHeight: currentHeight,
coin: coin,
),
const SizedBox(
width: 16,
@ -411,7 +415,9 @@ class _TransactionDetailsViewState
_transaction.isCancelled
? "Cancelled"
: whatIsIt(
_transaction.txType),
_transaction.type,
currentHeight,
),
style:
STextStyles.desktopTextMedium(
context),
@ -489,6 +495,8 @@ class _TransactionDetailsViewState
if (!isDesktop)
TxIcon(
transaction: _transaction,
currentHeight: currentHeight,
coin: coin,
),
],
),
@ -523,13 +531,17 @@ class _TransactionDetailsViewState
SelectableText(
_transaction.isCancelled
? "Cancelled"
: whatIsIt(_transaction.txType),
: whatIsIt(
_transaction.type,
currentHeight,
),
style: isDesktop
? STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: _transaction.txType == "Sent"
color: _transaction.type ==
TransactionType.outgoing
? Theme.of(context)
.extension<StackColors>()!
.accentColorOrange
@ -546,11 +558,12 @@ class _TransactionDetailsViewState
),
if (!((coin == Coin.monero ||
coin == Coin.wownero) &&
_transaction.txType.toLowerCase() ==
"sent") &&
_transaction.type ==
TransactionType.outgoing) &&
!((coin == Coin.firo ||
coin == Coin.firoTestNet) &&
_transaction.subType == "mint"))
_transaction.subType ==
TransactionSubType.mint))
isDesktop
? const _Divider()
: const SizedBox(
@ -558,11 +571,12 @@ class _TransactionDetailsViewState
),
if (!((coin == Coin.monero ||
coin == Coin.wownero) &&
_transaction.txType.toLowerCase() ==
"sent") &&
_transaction.type ==
TransactionType.outgoing) &&
!((coin == Coin.firo ||
coin == Coin.firoTestNet) &&
_transaction.subType == "mint"))
_transaction.subType ==
TransactionSubType.mint))
RoundedWhiteContainer(
padding: isDesktop
? const EdgeInsets.all(16)
@ -578,8 +592,8 @@ class _TransactionDetailsViewState
CrossAxisAlignment.start,
children: [
Text(
_transaction.txType.toLowerCase() ==
"sent"
_transaction.type ==
TransactionType.outgoing
? "Sent to"
: "Receiving address",
style: isDesktop
@ -592,17 +606,19 @@ class _TransactionDetailsViewState
const SizedBox(
height: 8,
),
_transaction.txType.toLowerCase() ==
"received"
_transaction.type ==
TransactionType.incoming
? FutureBuilder(
future: fetchContactNameFor(
_transaction.address),
_transaction.address
.value!.value),
builder: (builderContext,
AsyncSnapshot<String>
snapshot) {
String
addressOrContactName =
_transaction.address;
_transaction.address
.value!.value;
if (snapshot.connectionState ==
ConnectionState
.done &&
@ -630,7 +646,8 @@ class _TransactionDetailsViewState
},
)
: SelectableText(
_transaction.address,
_transaction
.address.value!.value,
style: isDesktop
? STextStyles
.desktopTextExtraExtraSmall(
@ -651,7 +668,7 @@ class _TransactionDetailsViewState
),
if (isDesktop)
IconCopyButton(
data: _transaction.address,
data: _transaction.address.value!.value,
),
],
),
@ -855,7 +872,10 @@ class _TransactionDetailsViewState
: const EdgeInsets.all(12),
child: Builder(builder: (context) {
final feeString = showFeePending
? _transaction.confirmedStatus
? _transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
)
? Format.localizedStringAsFixed(
value: fee,
locale: ref.watch(
@ -947,9 +967,14 @@ class _TransactionDetailsViewState
: const EdgeInsets.all(12),
child: Builder(builder: (context) {
final height = widget.coin != Coin.epicCash &&
_transaction.confirmedStatus
_transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
)
? "${_transaction.height == 0 ? "Unknown" : _transaction.height}"
: _transaction.confirmations > 0
: _transaction.getConfirmations(
currentHeight) >
0
? "${_transaction.height}"
: "Pending";
@ -1297,9 +1322,13 @@ class _TransactionDetailsViewState
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: (coin == Coin.epicCash &&
_transaction.confirmedStatus == false &&
_transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
) ==
false &&
_transaction.isCancelled == false &&
_transaction.txType == "Sent")
_transaction.type == TransactionType.outgoing)
? SizedBox(
width: MediaQuery.of(context).size.width - 32,
child: TextButton(

View file

@ -217,8 +217,8 @@ class _FavoriteCardState extends ConsumerState<FavoriteCard> {
),
),
FutureBuilder(
future: ref.watch(
managerProvider.select((value) => value.totalBalance)),
future: Future(() => ref.watch(managerProvider
.select((value) => value.balance.getTotal()))),
builder: (builderContext, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {

View file

@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_card.dart';
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart';
@ -22,6 +24,8 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/transaction_card.dart';
import 'package:tuple/tuple.dart';
import '../../../db/main_db.dart';
class DesktopContactDetails extends ConsumerStatefulWidget {
const DesktopContactDetails({
Key? key,
@ -57,11 +61,13 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
List<Tuple2<String, Transaction>> result = [];
for (final manager in managers) {
final transactions = (await manager.transactionData)
.getAllTransactions()
.values
.toList()
.where((e) => _contactHasAddress(e.address, contact));
final transactions = await MainDB.instance
.getTransactions(manager.walletId)
.filter()
.anyOf(contact.addresses.map((e) => e.address),
(q, String e) => q.address((q) => q.valueEqualTo(e)))
.sortByTimestampDesc()
.findAll();
for (final tx in transactions) {
result.add(Tuple2(manager.walletId, tx));

View file

@ -4,12 +4,15 @@ import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
import 'package:stackwallet/providers/exchange/trade_sent_from_stack_lookup_provider.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/format.dart';
@ -26,7 +29,7 @@ import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'package:tuple/tuple.dart';
import '../../route_generator.dart';
import '../../db/main_db.dart';
class DesktopAllTradesView extends ConsumerStatefulWidget {
const DesktopAllTradesView({Key? key}) : super(key: key);
@ -349,10 +352,12 @@ class _DesktopTradeRowCardState extends ConsumerState<DesktopTradeRowCard> {
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
// TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
final txData = await manager.transactionData;
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
final tx = txData.getAllTransactions()[txid];
await showDialog<void>(
context: context,
builder: (context) => DesktopDialog(

View file

@ -305,8 +305,9 @@ class _BalanceDisplayState extends ConsumerState<BalanceDisplay> {
final locale = ref.watch(
localeServiceChangeNotifierProvider.select((value) => value.locale));
// TODO redo this widget now that its not actually a future
return FutureBuilder(
future: manager.availableBalance,
future: Future(() => manager.balance.getSpendable()),
builder: (context, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&

View file

@ -2,6 +2,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart';
import 'package:stackwallet/providers/exchange/trade_sent_from_stack_lookup_provider.dart';
@ -17,6 +19,8 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/trade_card.dart';
import '../../../db/main_db.dart';
class DesktopTradeHistory extends ConsumerStatefulWidget {
const DesktopTradeHistory({Key? key}) : super(key: key);
@ -126,10 +130,11 @@ class _DesktopTradeHistoryState extends ConsumerState<DesktopTradeHistory> {
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
// TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
final txData = await manager.transactionData;
final tx = txData.getAllTransactions()[txid];
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
if (mounted) {
await showDialog<void>(

View file

@ -40,6 +40,7 @@ class CoinWalletsTable extends ConsumerWidget {
children: [
for (int i = 0; i < walletIds.length; i++)
Column(
key: Key("${coin.name}_$runtimeType${walletIds[i]}_key"),
children: [
if (i != 0)
const SizedBox(

View file

@ -37,6 +37,7 @@ class _WalletTableState extends ConsumerState<WalletSummaryTable> {
rows: [
for (int i = 0; i < providersByCoin.length; i++)
Builder(
key: Key("${providersByCoin[i].key.name}_${runtimeType}_key"),
builder: (context) {
final providers = ref.watch(walletsChangeNotifierProvider.select(
(value) => value

View file

@ -97,73 +97,73 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId);
// TODO: remove the need for this!!
final bool isOwnAddress = await manager.isOwnAddress(_address!);
if (isOwnAddress) {
await showDialog<dynamic>(
context: context,
useSafeArea: false,
barrierDismissible: true,
builder: (context) {
return DesktopDialog(
maxWidth: 400,
maxHeight: double.infinity,
child: Padding(
padding: const EdgeInsets.only(
left: 32,
bottom: 32,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Transaction failed",
style: STextStyles.desktopH3(context),
),
const DesktopDialogCloseButton(),
],
),
const SizedBox(
height: 12,
),
Text(
"Sending to self is currently disabled",
textAlign: TextAlign.left,
style: STextStyles.desktopTextExtraExtraSmall(context)
.copyWith(
fontSize: 18,
),
),
const SizedBox(
height: 40,
),
Row(
children: [
Expanded(
child: SecondaryButton(
buttonHeight: ButtonHeight.l,
label: "Ok",
onPressed: () {
Navigator.of(context).pop();
},
),
),
const SizedBox(
width: 32,
),
],
),
],
),
),
);
},
);
return;
}
// // TODO: remove the need for this!!
// final bool isOwnAddress = await manager.isOwnAddress(_address!);
// if (isOwnAddress) {
// await showDialog<dynamic>(
// context: context,
// useSafeArea: false,
// barrierDismissible: true,
// builder: (context) {
// return DesktopDialog(
// maxWidth: 400,
// maxHeight: double.infinity,
// child: Padding(
// padding: const EdgeInsets.only(
// left: 32,
// bottom: 32,
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text(
// "Transaction failed",
// style: STextStyles.desktopH3(context),
// ),
// const DesktopDialogCloseButton(),
// ],
// ),
// const SizedBox(
// height: 12,
// ),
// Text(
// "Sending to self is currently disabled",
// textAlign: TextAlign.left,
// style: STextStyles.desktopTextExtraExtraSmall(context)
// .copyWith(
// fontSize: 18,
// ),
// ),
// const SizedBox(
// height: 40,
// ),
// Row(
// children: [
// Expanded(
// child: SecondaryButton(
// buttonHeight: ButtonHeight.l,
// label: "Ok",
// onPressed: () {
// Navigator.of(context).pop();
// },
// ),
// ),
// const SizedBox(
// width: 32,
// ),
// ],
// ),
// ],
// ),
// ),
// );
// },
// );
// return;
// }
final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin);
int availableBalance;
@ -171,16 +171,14 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
if (ref.read(publicPrivateBalanceStateProvider.state).state ==
"Private") {
availableBalance = Format.decimalAmountToSatoshis(
await (manager.wallet as FiroWallet).availablePrivateBalance(),
coin);
(manager.wallet as FiroWallet).availablePrivateBalance(), coin);
} else {
availableBalance = Format.decimalAmountToSatoshis(
await (manager.wallet as FiroWallet).availablePublicBalance(),
coin);
(manager.wallet as FiroWallet).availablePublicBalance(), coin);
}
} else {
availableBalance =
Format.decimalAmountToSatoshis(await manager.availableBalance, coin);
Format.decimalAmountToSatoshis(manager.balance.getSpendable(), coin);
}
// confirm send all
@ -568,9 +566,9 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
if (wallet != null) {
Decimal? balance;
if (private) {
balance = await wallet.availablePrivateBalance();
balance = wallet.availablePrivateBalance();
} else {
balance = await wallet.availablePublicBalance();
balance = wallet.availablePublicBalance();
}
return Format.localizedStringAsFixed(
@ -757,19 +755,18 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
.wallet as FiroWallet;
if (ref.read(publicPrivateBalanceStateProvider.state).state ==
"Private") {
cryptoAmountController.text =
(await firoWallet.availablePrivateBalance())
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
cryptoAmountController.text = (firoWallet.availablePrivateBalance())
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
} else {
cryptoAmountController.text =
(await firoWallet.availablePublicBalance())
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
cryptoAmountController.text = (firoWallet.availablePublicBalance())
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
}
} else {
cryptoAmountController.text = (await ref
cryptoAmountController.text = (ref
.read(walletsChangeNotifierProvider)
.getManager(walletId)
.availableBalance)
.balance
.getSpendable())
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
}
}

View file

@ -68,15 +68,17 @@ class _WDesktopWalletSummaryState extends State<DesktopWalletSummary> {
final firoWallet = ref.watch(
managerProvider.select((value) => value.wallet))
as FiroWallet;
totalBalanceFuture = firoWallet.availablePublicBalance();
availableBalanceFuture =
firoWallet.availablePrivateBalance();
totalBalanceFuture =
Future(() => firoWallet.balance.getSpendable());
availableBalanceFuture = Future(
() => firoWallet.balancePrivate.getSpendable());
} else {
totalBalanceFuture = ref.watch(managerProvider
.select((value) => value.totalBalance));
availableBalanceFuture = ref.watch(managerProvider
.select((value) => value.availableBalance));
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
totalBalanceFuture =
Future(() => manager.balance.getTotal());
availableBalanceFuture =
Future(() => manager.balance.getSpendable());
}
final locale = ref.watch(localeServiceChangeNotifierProvider

View file

@ -13,12 +13,17 @@ import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.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/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import '../../hive/db.dart';
import '../../utilities/db_version_migration.dart';
import '../../utilities/logger.dart';
class DesktopLoginView extends ConsumerStatefulWidget {
const DesktopLoginView({
Key? key,
@ -43,6 +48,25 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
bool hidePassword = true;
bool _continueEnabled = false;
Future<void> _checkDesktopMigrate() async {
if (Util.isDesktop) {
int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
0;
if (dbVersion < Constants.currentHiveDbVersion) {
try {
await DbVersionMigrator().migrate(
dbVersion,
secureStore: ref.read(secureStoreProvider),
);
} catch (e, s) {
Logging.instance.log("Cannot migrate desktop database\n$e $s",
level: LogLevel.Error, printFullLength: true);
}
}
}
}
Future<void> login() async {
try {
unawaited(
@ -63,12 +87,18 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
await Future<void>.delayed(const Duration(seconds: 1));
// init security context
await ref
.read(storageCryptoHandlerProvider)
.initFromExisting(passwordController.text);
// init desktop secure storage
await (ref.read(secureStoreProvider).store as DesktopSecureStore).init();
// check and migrate if needed
await _checkDesktopMigrate();
// load data
await widget.load?.call();
// if no errors passphrase is correct

View file

@ -0,0 +1,6 @@
import 'package:dart_numerics/dart_numerics.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
final currentHeightProvider =
StateProvider.family<int, Coin>((ref, coin) => int64MaxValue);

View file

@ -5,7 +5,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart';
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
@ -122,6 +121,8 @@ import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:tuple/tuple.dart';
import 'models/isar/models/blockchain_data/transaction.dart';
class RouteGenerator {
static const bool useMaterialPageRoute = true;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,14 +3,14 @@ import 'dart:typed_data';
import 'package:bip47/bip47.dart';
import 'package:bip47/src/util.dart';
import 'package:bitcoindart/bitcoindart.dart';
import 'package:bitcoindart/bitcoindart.dart' as btc_dart;
import 'package:bitcoindart/src/utils/constants/op.dart' as op;
import 'package:bitcoindart/src/utils/script.dart' as bscript;
import 'package:decimal/decimal.dart';
import 'package:isar/isar.dart';
import 'package:pointycastle/digests/sha256.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/models.dart' as models;
import 'package:stackwallet/models/paymint/utxo_model.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -59,7 +59,8 @@ extension PayNym on DogecoinWallet {
Future<Uint8List> signWithNotificationKey(Uint8List data) async {
final node = getBip32Root((await mnemonic).join(" "), network)
.derivePath("m/47'/0'/0'");
final pair = ECPair.fromPrivateKey(node.privateKey!, network: network);
final pair =
btc_dart.ECPair.fromPrivateKey(node.privateKey!, network: network);
final signed = pair.sign(SHA256Digest().process(data));
return signed;
}
@ -130,24 +131,22 @@ extension PayNym on DogecoinWallet {
}
/// return the notification tx sent from my wallet if it exists
Future<models.Transaction?> hasSentNotificationTx(PaymentCode pCode) async {
final txData = await transactionData;
for (final tx in txData.getAllTransactions().values) {
if (tx.address == pCode.notificationAddress()) {
return tx;
}
}
return null;
Future<Transaction?> hasSentNotificationTx(PaymentCode pCode) async {
final tx = await db
.getTransactions(walletId)
.filter()
.address((q) => q.valueEqualTo(pCode.notificationAddress()))
.findFirst();
return tx;
}
void preparePaymentCodeSend(PaymentCode pCode) async {
final notifTx = await hasSentNotificationTx(pCode);
final currentHeight = await chainHeight;
if (notifTx == null) {
throw PaynymSendException("No notification transaction sent to $pCode");
} else if (!notifTx.confirmedStatus) {
} else if (!notifTx.isConfirmed(currentHeight, MINIMUM_CONFIRMATIONS)) {
throw PaynymSendException(
"Notification transaction sent to $pCode has not confirmed yet");
} else {
@ -230,17 +229,19 @@ extension PayNym on DogecoinWallet {
required int selectedTxFeeRate,
required String targetPaymentCodeString,
int additionalOutputs = 0,
List<UtxoObject>? utxos,
List<UTXO>? utxos,
}) async {
const amountToSend = DUST_LIMIT;
final List<UtxoObject> availableOutputs = utxos ?? outputsList;
final List<UtxoObject> spendableOutputs = [];
final List<UTXO> availableOutputs = utxos ?? await this.utxos;
final List<UTXO> spendableOutputs = [];
int spendableSatoshiValue = 0;
// Build list of spendable outputs and totaling their satoshi amount
for (var i = 0; i < availableOutputs.length; i++) {
if (availableOutputs[i].blocked == false &&
availableOutputs[i].status.confirmed == true) {
if (availableOutputs[i].isBlocked == false &&
availableOutputs[i]
.isConfirmed(await chainHeight, MINIMUM_CONFIRMATIONS) ==
true) {
spendableOutputs.add(availableOutputs[i]);
spendableSatoshiValue += availableOutputs[i].value;
}
@ -257,12 +258,11 @@ extension PayNym on DogecoinWallet {
}
// sort spendable by age (oldest first)
spendableOutputs.sort(
(a, b) => b.status.confirmations.compareTo(a.status.confirmations));
spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!));
int satoshisBeingUsed = 0;
int outputsBeingUsed = 0;
List<UtxoObject> utxoObjectsToUse = [];
List<UTXO> utxoObjectsToUse = [];
for (int i = 0;
satoshisBeingUsed < amountToSend && i < spendableOutputs.length;
@ -403,7 +403,7 @@ extension PayNym on DogecoinWallet {
// equal to its vSize
Future<Tuple2<String, int>> _createNotificationTx({
required String targetPaymentCodeString,
required List<UtxoObject> utxosToUse,
required List<UTXO> utxosToUse,
required Map<String, dynamic> utxoSigningData,
required int change,
}) async {
@ -420,7 +420,7 @@ extension PayNym on DogecoinWallet {
final buffer = rev.buffer.asByteData();
buffer.setUint32(txPoint.length, txPointIndex, Endian.little);
final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as ECPair;
final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair;
final S = SecretPoint(
myKeyPair.privateKey!,
@ -440,7 +440,7 @@ extension PayNym on DogecoinWallet {
]);
// build a notification tx
final txb = TransactionBuilder(network: network);
final txb = btc_dart.TransactionBuilder(network: network);
txb.setVersion(1);
txb.addInput(
@ -454,9 +454,8 @@ extension PayNym on DogecoinWallet {
// TODO: add possible change output and mark output as dangerous
if (change > 0) {
// generate new change address if current change address has been used
await checkChangeAddressForTransactions(DerivePathType.bip44);
final String changeAddress =
await getCurrentAddressForChain(1, DerivePathType.bip44);
await checkChangeAddressForTransactions();
final String changeAddress = await currentChangeAddress;
txb.addOutput(changeAddress, change);
}
@ -470,7 +469,7 @@ extension PayNym on DogecoinWallet {
final txid = utxosToUse[i].txid;
txb.sign(
vin: i,
keyPair: utxoSigningData[txid]["keyPair"] as ECPair,
keyPair: utxoSigningData[txid]["keyPair"] as btc_dart.ECPair,
// witnessValue: utxosToUse[i].value,
);
}
@ -563,15 +562,24 @@ extension PayNym on DogecoinWallet {
}
}
Future<Map<String, dynamic>> parseTransaction(
Future<Tuple4<Transaction, List<Output>, List<Input>, Address>>
parseTransaction(
Map<String, dynamic> txData,
dynamic electrumxClient,
Set<String> myAddresses,
Set<String> myChangeAddresses,
List<Address> myAddresses,
Coin coin,
int minConfirms,
Decimal currentPrice,
String walletId,
) async {
Set<String> receivingAddresses = myAddresses
.where((e) => e.subType == AddressSubType.receiving)
.map((e) => e.value)
.toSet();
Set<String> changeAddresses = myAddresses
.where((e) => e.subType == AddressSubType.change)
.map((e) => e.value)
.toSet();
Set<String> inputAddresses = {};
Set<String> outputAddresses = {};
@ -580,6 +588,7 @@ Future<Map<String, dynamic>> parseTransaction(
int amountSentFromWallet = 0;
int amountReceivedInWallet = 0;
int changeAmount = 0;
// parse inputs
for (final input in txData["vin"] as List) {
@ -612,7 +621,8 @@ Future<Map<String, dynamic>> parseTransaction(
inputAddresses.add(address);
// if input was from my wallet, add value to amount sent
if (myAddresses.contains(address)) {
if (receivingAddresses.contains(address) ||
changeAddresses.contains(address)) {
amountSentFromWallet += value;
}
}
@ -637,61 +647,110 @@ Future<Map<String, dynamic>> parseTransaction(
if (address != null) {
outputAddresses.add(address);
// if output was from my wallet, add value to amount received
if (myAddresses.contains(address)) {
// if output was to my wallet, add value to amount received
if (receivingAddresses.contains(address)) {
amountReceivedInWallet += value;
} else if (changeAddresses.contains(address)) {
changeAmount += value;
}
}
}
final mySentFromAddresses = myAddresses.intersection(inputAddresses);
final myReceivedOnAddresses = myAddresses.intersection(outputAddresses);
final mySentFromAddresses = [
...receivingAddresses.intersection(inputAddresses),
...changeAddresses.intersection(inputAddresses)
];
final myReceivedOnAddresses =
receivingAddresses.intersection(outputAddresses);
final myChangeReceivedOnAddresses =
changeAddresses.intersection(outputAddresses);
final fee = totalInputValue - totalOutputValue;
// create normalized tx data map
Map<String, dynamic> normalizedTx = {};
final int confirms = txData["confirmations"] as int? ?? 0;
normalizedTx["txid"] = txData["txid"] as String;
normalizedTx["confirmed_status"] = confirms >= minConfirms;
normalizedTx["confirmations"] = confirms;
normalizedTx["timestamp"] = txData["blocktime"] as int? ??
(DateTime.now().millisecondsSinceEpoch ~/ 1000);
normalizedTx["aliens"] = <dynamic>[];
normalizedTx["fees"] = fee;
normalizedTx["address"] = txData["address"] as String;
normalizedTx["inputSize"] = txData["vin"].length;
normalizedTx["outputSize"] = txData["vout"].length;
normalizedTx["inputs"] = txData["vin"];
normalizedTx["outputs"] = txData["vout"];
normalizedTx["height"] = txData["height"] as int;
// this is the address initially used to fetch the txid
Address transactionAddress = txData["address"] as Address;
TransactionType type;
int amount;
String type;
if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) {
// tx is sent to self
type = "Sent to self";
amount = amountSentFromWallet - amountReceivedInWallet - fee;
type = TransactionType.sentToSelf;
// should be 0
amount = amountSentFromWallet - amountReceivedInWallet - fee - changeAmount;
} else if (mySentFromAddresses.isNotEmpty) {
// outgoing tx
type = "Sent";
amount = amountSentFromWallet;
type = TransactionType.outgoing;
amount = amountSentFromWallet - changeAmount - fee;
final possible =
outputAddresses.difference(myChangeReceivedOnAddresses).first;
if (transactionAddress.value != possible) {
transactionAddress = Address(
walletId: walletId,
value: possible,
derivationIndex: -1,
subType: AddressSubType.nonWallet,
type: AddressType.nonWallet,
publicKey: [],
);
}
} else {
// incoming tx
type = "Received";
type = TransactionType.incoming;
amount = amountReceivedInWallet;
}
normalizedTx["txType"] = type;
normalizedTx["amount"] = amount;
normalizedTx["worthNow"] = (Format.satoshisToAmount(
amount,
coin: coin,
) *
currentPrice)
.toStringAsFixed(2);
final tx = Transaction(
walletId: walletId,
txid: txData["txid"] as String,
timestamp: txData["blocktime"] as int? ??
(DateTime.now().millisecondsSinceEpoch ~/ 1000),
type: type,
subType: TransactionSubType.none,
amount: amount,
fee: fee,
height: txData["height"] as int?,
isCancelled: false,
isLelantus: false,
slateId: null,
otherData: null,
);
return normalizedTx;
List<Output> outs = [];
List<Input> ins = [];
for (final json in txData["vin"] as List) {
bool isCoinBase = json['coinbase'] != null;
final input = Input(
walletId: walletId,
txid: json['txid'] as String,
vout: json['vout'] as int? ?? -1,
scriptSig: json['scriptSig']?['hex'] as String?,
scriptSigAsm: json['scriptSig']?['asm'] as String?,
isCoinbase: isCoinBase ? isCoinBase : json['is_coinbase'] as bool?,
sequence: json['sequence'] as int?,
innerRedeemScriptAsm: json['innerRedeemscriptAsm'] as String?,
);
ins.add(input);
}
for (final json in txData["vout"] as List) {
final output = Output(
walletId: walletId,
scriptPubKey: json['scriptPubKey']?['hex'] as String?,
scriptPubKeyAsm: json['scriptPubKey']?['asm'] as String?,
scriptPubKeyType: json['scriptPubKey']?['type'] as String?,
scriptPubKeyAddress: json["scriptPubKey"]?["addresses"]?[0] as String? ??
json['scriptPubKey']['type'] as String,
value: Format.decimalAmountToSatoshis(
Decimal.parse(json["value"].toString()),
coin,
),
);
outs.add(output);
}
return Tuple4(tx, outs, ins, transactionAddress);
}

View file

@ -1,13 +1,15 @@
import 'package:decimal/decimal.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/models.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/litecoin/litecoin_wallet.dart';
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
import 'package:stackwallet/services/coins/particl/particl_wallet.dart';
@ -17,8 +19,6 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'litecoin/litecoin_wallet.dart';
abstract class CoinServiceAPI {
CoinServiceAPI();
@ -240,30 +240,15 @@ abstract class CoinServiceAPI {
Future<String> confirmSend({required Map<String, dynamic> txData});
/// create and submit tx to network
///
/// Returns the txid of the sent tx
/// will throw exceptions on failure
Future<String> send(
{required String toAddress,
required int amount,
Map<String, String> args});
Future<FeeObject> get fees;
Future<int> get maxFee;
Future<String> get currentReceivingAddress;
// Future<String> get currentLegacyReceivingAddress;
Future<Decimal> get availableBalance;
Future<Decimal> get pendingBalance;
Future<Decimal> get totalBalance;
Future<Decimal> get balanceMinusMaxFee;
Balance get balance;
Future<List<String>> get allOwnAddresses;
Future<TransactionData> get transactionData;
Future<List<UtxoObject>> get unspentOutputs;
Future<List<isar_models.Transaction>> get transactions;
Future<List<isar_models.UTXO>> get utxos;
Future<void> refresh();
@ -307,4 +292,6 @@ abstract class CoinServiceAPI {
// used for electrumx coins
Future<void> updateSentCachedTxData(Map<String, dynamic> txData);
int get storedChainHeight;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
import 'dart:async';
import 'package:decimal/decimal.dart';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.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';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
@ -59,7 +60,6 @@ class Manager with ChangeNotifier {
Future<void> updateNode(bool shouldRefresh) async {
await _currentWallet.updateNode(shouldRefresh);
}
// Function(bool isActive)? onIsActiveWalletChanged;
CoinServiceAPI get wallet => _currentWallet;
@ -120,73 +120,17 @@ class Manager with ChangeNotifier {
}
}
/// create and submit tx to network
///
/// Returns the txid of the sent tx
/// will throw exceptions on failure
Future<String> send({
required String toAddress,
required int amount,
Map<String, String> args = const {},
}) async {
try {
final txid = await _currentWallet.send(
toAddress: toAddress,
amount: amount,
args: args,
);
notifyListeners();
return txid;
} catch (e, s) {
Logging.instance.log("$e\n $s", level: LogLevel.Error);
// rethrow to pass error in alert
rethrow;
}
}
Future<FeeObject> get fees => _currentWallet.fees;
Future<int> get maxFee => _currentWallet.maxFee;
Future<String> get currentReceivingAddress =>
_currentWallet.currentReceivingAddress;
// Future<String> get currentLegacyReceivingAddress =>
// _currentWallet.currentLegacyReceivingAddress;
Future<Decimal> get availableBalance async {
_cachedAvailableBalance = await _currentWallet.availableBalance;
return _cachedAvailableBalance;
}
Balance get balance => _currentWallet.balance;
Decimal _cachedAvailableBalance = Decimal.zero;
Decimal get cachedAvailableBalance => _cachedAvailableBalance;
Future<Decimal> get pendingBalance => _currentWallet.pendingBalance;
Future<Decimal> get balanceMinusMaxFee => _currentWallet.balanceMinusMaxFee;
Future<Decimal> get totalBalance async {
_cachedTotalBalance = await _currentWallet.totalBalance;
return _cachedTotalBalance;
}
Decimal _cachedTotalBalance = Decimal.zero;
Decimal get cachedTotalBalance => _cachedTotalBalance;
// Future<Decimal> get fiatBalance async {
// final balance = await _currentWallet.availableBalance;
// final price = await _currentWallet.basePrice;
// return balance * price;
// }
//
// Future<Decimal> get fiatTotalBalance async {
// final balance = await _currentWallet.totalBalance;
// final price = await _currentWallet.basePrice;
// return balance * price;
// }
Future<List<String>> get allOwnAddresses => _currentWallet.allOwnAddresses;
Future<TransactionData> get transactionData => _currentWallet.transactionData;
Future<List<UtxoObject>> get unspentOutputs => _currentWallet.unspentOutputs;
Future<List<isar_models.Transaction>> get transactions =>
_currentWallet.transactions;
Future<List<isar_models.UTXO>> get utxos => _currentWallet.utxos;
Future<void> refresh() async {
await _currentWallet.refresh();
@ -233,11 +177,6 @@ class Manager with ChangeNotifier {
}
}
// Future<bool> initializeWallet() async {
// final success = await _currentWallet.initializeWallet();
// return success;
// }
Future<void> exitCurrentWallet() async {
final name = _currentWallet.walletName;
final id = _currentWallet.walletId;
@ -260,11 +199,6 @@ class Manager with ChangeNotifier {
}
}
Future<bool> isOwnAddress(String address) async {
final allOwnAddresses = await this.allOwnAddresses;
return allOwnAddresses.contains(address);
}
bool get isConnected => _currentWallet.isConnected;
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
@ -278,4 +212,6 @@ class Manager with ChangeNotifier {
}
return success;
}
int get currentHeight => _currentWallet.storedChainHeight;
}

View file

@ -21,21 +21,23 @@ import 'package:flutter_libmonero/core/key_service.dart';
import 'package:flutter_libmonero/core/wallet_creation_service.dart';
import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/view_model/send/output.dart' as monero_output;
import 'package:http/http.dart';
import 'package:isar/isar.dart';
import 'package:mutex/mutex.dart';
import 'package:stackwallet/db/main_db.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/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/paymint/utxo_model.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart';
import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_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/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/price.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -45,17 +47,18 @@ import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
import 'package:tuple/tuple.dart';
const int MINIMUM_CONFIRMATIONS = 10;
class MoneroWallet extends CoinServiceAPI {
final String _walletId;
final Coin _coin;
final PriceAPI _priceAPI;
final SecureStorageInterface _secureStorage;
final Prefs _prefs;
class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
late final String _walletId;
late final Coin _coin;
late final SecureStorageInterface _secureStorage;
late final Prefs _prefs;
late String _walletName;
String _walletName;
bool _shouldAutoSync = false;
bool _isConnected = false;
bool _hasCalledExit = false;
@ -68,9 +71,9 @@ class MoneroWallet extends CoinServiceAPI {
WalletCreationService? _walletCreationService;
Timer? _autoSaveTimer;
Future<String>? _currentReceivingAddress;
Future<isar_models.Address?> get _currentReceivingAddress =>
db.getAddresses(walletId).sortByDerivationIndexDesc().findFirst();
Future<FeeObject>? _feeObject;
Future<TransactionData>? _transactionData;
Mutex prepareSendMutex = Mutex();
Mutex estimateFeeMutex = Mutex();
@ -80,34 +83,29 @@ class MoneroWallet extends CoinServiceAPI {
required String walletName,
required Coin coin,
required SecureStorageInterface secureStorage,
PriceAPI? priceAPI,
Prefs? prefs,
}) : _walletId = walletId,
_walletName = walletName,
_coin = coin,
_priceAPI = priceAPI ?? PriceAPI(Client()),
_secureStorage = secureStorage,
_prefs = prefs ?? Prefs.instance;
@override
bool get isFavorite {
try {
return DB.instance.get<dynamic>(boxName: walletId, key: "isFavorite")
as bool;
} catch (e, s) {
Logging.instance.log(
"isFavorite fetch failed (returning false by default): $e\n$s",
level: LogLevel.Error);
return false;
}
MainDB? mockableOverride,
}) {
_walletId = walletId;
_walletName = walletName;
_coin = coin;
_secureStorage = secureStorage;
_prefs = prefs ?? Prefs.instance;
initCache(walletId, coin);
isarInit(mockableOverride: mockableOverride);
}
@override
set isFavorite(bool markFavorite) {
DB.instance.put<dynamic>(
boxName: walletId, key: "isFavorite", value: markFavorite);
_isFavorite = markFavorite;
updateCachedIsFavorite(markFavorite);
}
@override
bool get isFavorite => _isFavorite ??= getCachedIsFavorite();
bool? _isFavorite;
@override
bool get shouldAutoSync => _shouldAutoSync;
@ -139,23 +137,6 @@ class MoneroWallet extends CoinServiceAPI {
@override
set walletName(String newName) => _walletName = newName;
@override
// not used for monero
Future<List<String>> get allOwnAddresses async => [];
@override
Future<Decimal> get availableBalance async {
int runningBalance = 0;
for (final entry in walletBase!.balance!.entries) {
runningBalance += entry.value.unlockedBalance;
}
return Format.satoshisToAmount(runningBalance, coin: coin);
}
@override
// not used
Future<Decimal> get balanceMinusMaxFee => throw UnimplementedError();
@override
Coin get coin => _coin;
@ -184,8 +165,9 @@ class MoneroWallet extends CoinServiceAPI {
}
@override
Future<String> get currentReceivingAddress =>
_currentReceivingAddress ??= _getCurrentAddressForChain(0);
Future<String> get currentReceivingAddress async =>
(await _currentReceivingAddress)?.value ??
(await _generateAddressForChain(0, 0)).value;
@override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
@ -236,30 +218,30 @@ class MoneroWallet extends CoinServiceAPI {
int maxUnusedAddressGap,
int maxNumberOfIndexesToCheck,
) async {
// clear blockchain info
await db.deleteWalletBlockchainData(walletId);
var restoreHeight = walletBase?.walletInfo.restoreHeight;
highestPercentCached = 0;
await walletBase?.rescan(height: restoreHeight);
await refresh();
}
@override
Future<bool> generateNewAddress() async {
try {
const String indexKey = "receivingIndex";
// First increment the receiving index
await _incrementAddressIndexForChain(0);
final newReceivingIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
final currentReceiving = await _currentReceivingAddress;
final newReceivingIndex = currentReceiving!.derivationIndex + 1;
// Use new index to derive a new receiving address
final newReceivingAddress =
await _generateAddressForChain(0, newReceivingIndex);
final newReceivingAddress = await _generateAddressForChain(
0,
newReceivingIndex,
);
// Add that new receiving address to the array of receiving addresses
await _addToAddressesArrayForChain(newReceivingAddress, 0);
// Set the new receiving address that the service
_currentReceivingAddress = Future(() => newReceivingAddress);
// Add that new receiving address
await db.putAddress(newReceivingAddress);
return true;
} catch (e, s) {
@ -280,7 +262,7 @@ class MoneroWallet extends CoinServiceAPI {
level: LogLevel.Info,
);
if ((DB.instance.get<dynamic>(boxName: walletId, key: "id")) == null) {
if (getCachedId() == null) {
throw Exception(
"Attempted to initialize an existing wallet using an unknown wallet ID!");
}
@ -290,6 +272,7 @@ class MoneroWallet extends CoinServiceAPI {
keysStorage = KeyService(_secureStorage);
await _prefs.init();
// final data =
// DB.instance.get<dynamic>(boxName: walletId, key: "latest_tx_model")
// as TransactionData?;
@ -314,14 +297,14 @@ class MoneroWallet extends CoinServiceAPI {
);
// Wallet already exists, triggers for a returning user
String indexKey = "receivingIndex";
final curIndex =
await DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(0, curIndex);
Logging.instance.log("xmr address in init existing: $newReceivingAddress",
level: LogLevel.Info);
_currentReceivingAddress = Future(() => newReceivingAddress);
// String indexKey = "receivingIndex";
// final curIndex =
// await DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
// // Use new index to derive a new receiving address
// final newReceivingAddress = await _generateAddressForChain(0, curIndex);
// Logging.instance.log("xmr address in init existing: $newReceivingAddress",
// level: LogLevel.Info);
// _currentReceivingAddress = Future(() => newReceivingAddress);
}
@override
@ -400,42 +383,18 @@ class MoneroWallet extends CoinServiceAPI {
await walletBase!.connectToNode(
node: Node(uri: "$host:${node.port}", type: WalletType.monero));
await walletBase!.startSync();
await DB.instance
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
// Set relevant indexes
await DB.instance
.put<dynamic>(boxName: walletId, key: "receivingIndex", value: 0);
await DB.instance
.put<dynamic>(boxName: walletId, key: "changeIndex", value: 0);
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'blocked_tx_hashes',
value: ["0xdefault"],
); // A list of transaction hashes to represent frozen utxos in wallet
// initialize address book entries
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'addressBookEntries',
value: <String, String>{});
await DB.instance
.put<dynamic>(boxName: walletId, key: "isFavorite", value: false);
await Future.wait([
updateCachedId(walletId),
updateCachedIsFavorite(false),
]);
// Generate and add addresses to relevant arrays
final initialReceivingAddress = await _generateAddressForChain(0, 0);
// final initialChangeAddress = await _generateAddressForChain(1, 0);
await _addToAddressesArrayForChain(initialReceivingAddress, 0);
// await _addToAddressesArrayForChain(initialChangeAddress, 1);
await db.putAddress(initialReceivingAddress);
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'receivingAddresses',
value: [initialReceivingAddress]);
await DB.instance
.put<dynamic>(boxName: walletId, key: "receivingIndex", value: 0);
_currentReceivingAddress = Future(() => initialReceivingAddress);
walletBase?.close();
Logging.instance
.log("initializeNew for $walletName $walletId", level: LogLevel.Info);
@ -462,10 +421,6 @@ class MoneroWallet extends CoinServiceAPI {
return data;
}
@override
// not used in xmr
Future<Decimal> get pendingBalance => throw UnimplementedError();
@override
Future<Map<String, dynamic>> prepareSend({
required String address,
@ -493,16 +448,15 @@ class MoneroWallet extends CoinServiceAPI {
try {
// check for send all
bool isSendAll = false;
final balance = await availableBalance;
final satInDecimal =
Format.satoshisToAmount(satoshiAmount, coin: coin);
if (satInDecimal == balance) {
final balance = await _availableBalance;
if (satoshiAmount == balance) {
isSendAll = true;
}
Logging.instance
.log("$toAddress $satoshiAmount $args", level: LogLevel.Info);
String amountToSend = satInDecimal
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
String amountToSend =
Format.satoshisToAmount(satoshiAmount, coin: coin)
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
Logging.instance
.log("$satoshiAmount $amountToSend", level: LogLevel.Info);
@ -637,28 +591,11 @@ class MoneroWallet extends CoinServiceAPI {
// walletBase!.onNewBlock = onNewBlock;
// walletBase!.onNewTransaction = onNewTransaction;
// walletBase!.syncStatusChanged = syncStatusChanged;
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'receivingAddresses',
value: [walletInfo.address!]);
await DB.instance
.put<dynamic>(boxName: walletId, key: "receivingIndex", value: 0);
await DB.instance
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
await DB.instance
.put<dynamic>(boxName: walletId, key: "changeIndex", value: 0);
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'blocked_tx_hashes',
value: ["0xdefault"],
); // A list of transaction hashes to represent frozen utxos in wallet
// initialize address book entries
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'addressBookEntries',
value: <String, String>{});
await DB.instance
.put<dynamic>(boxName: walletId, key: "isFavorite", value: false);
await Future.wait([
updateCachedId(walletId),
updateCachedIsFavorite(false),
]);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
@ -702,22 +639,10 @@ class MoneroWallet extends CoinServiceAPI {
),
);
final newTxData = await _fetchTransactionData();
_transactionData = Future(() => newTxData);
await _refreshTransactions();
await _updateBalance();
await _checkCurrentReceivingAddressesForTransactions();
String indexKey = "receivingIndex";
final curIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
// Use new index to derive a new receiving address
try {
final newReceivingAddress = await _generateAddressForChain(0, curIndex);
_currentReceivingAddress = Future(() => newReceivingAddress);
} catch (e, s) {
Logging.instance.log(
"Failed to call _generateAddressForChain(0, $curIndex): $e\n$s",
level: LogLevel.Error);
}
if (walletBase?.syncStatus is SyncedSyncStatus) {
refreshMutex = false;
@ -731,16 +656,6 @@ class MoneroWallet extends CoinServiceAPI {
}
}
@override
Future<String> send({
required String toAddress,
required int amount,
Map<String, String> args = const {},
}) {
// not used for xmr
throw UnimplementedError();
}
@override
Future<bool> testNetworkConnection() async {
return await walletBase?.isConnected() ?? false;
@ -807,8 +722,32 @@ class MoneroWallet extends CoinServiceAPI {
) as int? ??
0;
@override
Future<Decimal> get totalBalance async {
Future<void> _updateBalance() async {
final total = await _totalBalance;
final available = await _availableBalance;
_balance = Balance(
coin: coin,
total: total,
spendable: available,
blockedTotal: 0,
pendingSpendable: total - available,
);
await updateCachedBalance(_balance!);
}
Future<int> get _availableBalance async {
try {
int runningBalance = 0;
for (final entry in walletBase!.balance!.entries) {
runningBalance += entry.value.unlockedBalance;
}
return runningBalance;
} catch (_) {
return 0;
}
}
Future<int> get _totalBalance async {
try {
final balanceEntries = walletBase?.balance?.entries;
if (balanceEntries != null) {
@ -817,7 +756,7 @@ class MoneroWallet extends CoinServiceAPI {
bal = bal + element.value.fullBalance;
}
await _updateCachedBalance(bal);
return Format.satoshisToAmount(bal, coin: coin);
return bal;
} else {
final transactions = walletBase!.transactionHistory!.transactions;
int transactionBalance = 0;
@ -830,21 +769,13 @@ class MoneroWallet extends CoinServiceAPI {
}
await _updateCachedBalance(transactionBalance);
return Format.satoshisToAmount(transactionBalance, coin: coin);
return transactionBalance;
}
} catch (_) {
return Format.satoshisToAmount(_getCachedBalance(), coin: coin);
return _getCachedBalance();
}
}
@override
Future<TransactionData> get transactionData =>
_transactionData ??= _fetchTransactionData();
@override
// not used for xmr
Future<List<UtxoObject>> get unspentOutputs => throw UnimplementedError();
@override
Future<void> updateNode(bool shouldRefresh) async {
final node = await _getCurrentNode();
@ -873,66 +804,23 @@ class MoneroWallet extends CoinServiceAPI {
@override
String get walletId => _walletId;
/// Returns the latest receiving/change (external/internal) address for the wallet depending on [chain]
/// and
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
Future<String> _getCurrentAddressForChain(int chain) async {
// Here, we assume that chain == 1 if it isn't 0
String arrayKey = chain == 0 ? "receivingAddresses" : "changeAddresses";
final internalChainArray = (DB.instance
.get<dynamic>(boxName: walletId, key: arrayKey)) as List<dynamic>;
return internalChainArray.last as String;
}
/// Increases the index for either the internal or external chain, depending on [chain].
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
Future<void> _incrementAddressIndexForChain(int chain) async {
// Here we assume chain == 1 if it isn't 0
String indexKey = chain == 0 ? "receivingIndex" : "changeIndex";
final newIndex =
(DB.instance.get<dynamic>(boxName: walletId, key: indexKey)) + 1;
await DB.instance
.put<dynamic>(boxName: walletId, key: indexKey, value: newIndex);
}
Future<String> _generateAddressForChain(int chain, int index) async {
Future<isar_models.Address> _generateAddressForChain(
int chain,
int index,
) async {
//
String address = walletBase!.getTransactionAddress(chain, index);
return address;
}
/// Adds [address] to the relevant chain's address array, which is determined by [chain].
/// [address] - Expects a standard native segwit address
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
Future<void> _addToAddressesArrayForChain(String address, int chain) async {
String chainArray = '';
if (chain == 0) {
chainArray = 'receivingAddresses';
} else {
chainArray = 'changeAddresses';
}
final addressArray =
DB.instance.get<dynamic>(boxName: walletId, key: chainArray);
if (addressArray == null) {
Logging.instance.log(
'Attempting to add the following to $chainArray array for chain $chain:${[
address
]}',
level: LogLevel.Info);
await DB.instance
.put<dynamic>(boxName: walletId, key: chainArray, value: [address]);
} else {
// Make a deep copy of the existing list
final List<String> newArray = [];
addressArray
.forEach((dynamic _address) => newArray.add(_address as String));
newArray.add(address); // Add the address passed into the method
await DB.instance
.put<dynamic>(boxName: walletId, key: chainArray, value: newArray);
}
return isar_models.Address(
walletId: walletId,
derivationIndex: index,
value: address,
publicKey: [],
type: isar_models.AddressType.cryptonote,
subType: chain == 0
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.change,
);
}
Future<FeeObject> _getFees() async {
@ -947,7 +835,7 @@ class MoneroWallet extends CoinServiceAPI {
);
}
Future<TransactionData> _fetchTransactionData() async {
Future<void> _refreshTransactions() async {
await walletBase!.updateTransactions();
final transactions = walletBase?.transactionHistory!.transactions;
@ -965,123 +853,75 @@ class MoneroWallet extends CoinServiceAPI {
//
// final Set<String> cachedTxids = Set<String>.from(txidsList);
// sort thing stuff
// change to get Monero price
final priceData =
await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency);
Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero;
final List<Map<String, dynamic>> midSortedArray = [];
final List<
Tuple4<isar_models.Transaction, List<isar_models.Output>,
List<isar_models.Input>, isar_models.Address?>> txnsData = [];
if (transactions != null) {
for (var tx in transactions.entries) {
// cachedTxids.add(tx.value.id);
Logging.instance.log(
"${tx.value.accountIndex} ${tx.value.addressIndex} ${tx.value.amount} ${tx.value.date} "
"${tx.value.direction} ${tx.value.fee} ${tx.value.height} ${tx.value.id} ${tx.value.isPending} ${tx.value.key} "
"${tx.value.recipientAddress}, ${tx.value.additionalInfo} con:${tx.value.confirmations}"
" ${tx.value.keyIndex}",
level: LogLevel.Info);
final worthNow = (currentPrice *
Format.satoshisToAmount(
tx.value.amount!,
coin: coin,
))
.toStringAsFixed(2);
Map<String, dynamic> midSortedTx = {};
// // create final tx map
midSortedTx["txid"] = tx.value.id;
midSortedTx["confirmed_status"] = !tx.value.isPending &&
tx.value.confirmations! >= MINIMUM_CONFIRMATIONS;
midSortedTx["confirmations"] = tx.value.confirmations ?? 0;
midSortedTx["timestamp"] =
(tx.value.date.millisecondsSinceEpoch ~/ 1000);
midSortedTx["txType"] =
tx.value.direction == TransactionDirection.incoming
? "Received"
: "Sent";
midSortedTx["amount"] = tx.value.amount;
midSortedTx["worthNow"] = worthNow;
midSortedTx["worthAtBlockTimestamp"] = worthNow;
midSortedTx["fees"] = tx.value.fee;
// Logging.instance.log(
// "${tx.value.accountIndex} ${tx.value.addressIndex} ${tx.value.amount} ${tx.value.date} "
// "${tx.value.direction} ${tx.value.fee} ${tx.value.height} ${tx.value.id} ${tx.value.isPending} ${tx.value.key} "
// "${tx.value.recipientAddress}, ${tx.value.additionalInfo} con:${tx.value.confirmations}"
// " ${tx.value.keyIndex}",
// level: LogLevel.Info);
isar_models.Address? address;
isar_models.TransactionType type;
if (tx.value.direction == TransactionDirection.incoming) {
final addressInfo = tx.value.additionalInfo;
midSortedTx["address"] = walletBase?.getTransactionAddress(
final addressString = walletBase?.getTransactionAddress(
addressInfo!['accountIndex'] as int,
addressInfo['addressIndex'] as int,
);
if (addressString != null) {
address = await db
.getAddresses(walletId)
.filter()
.valueEqualTo(addressString)
.findFirst();
}
type = isar_models.TransactionType.incoming;
} else {
midSortedTx["address"] = "";
// txn.address = "";
type = isar_models.TransactionType.outgoing;
}
final int txHeight = tx.value.height ?? 0;
midSortedTx["height"] = txHeight;
// if (txHeight >= latestTxnBlockHeight) {
// latestTxnBlockHeight = txHeight;
// }
final txn = isar_models.Transaction(
walletId: walletId,
txid: tx.value.id,
timestamp: (tx.value.date.millisecondsSinceEpoch ~/ 1000),
type: type,
subType: isar_models.TransactionSubType.none,
amount: tx.value.amount ?? 0,
fee: tx.value.fee ?? 0,
height: tx.value.height,
isCancelled: false,
isLelantus: false,
slateId: null,
otherData: null,
);
midSortedTx["aliens"] = <dynamic>[];
midSortedTx["inputSize"] = 0;
midSortedTx["outputSize"] = 0;
midSortedTx["inputs"] = <dynamic>[];
midSortedTx["outputs"] = <dynamic>[];
midSortedArray.add(midSortedTx);
txnsData.add(Tuple4(txn, [], [], address));
}
}
// sort by date ----
midSortedArray
.sort((a, b) => (b["timestamp"] as int) - (a["timestamp"] as int));
Logging.instance.log(midSortedArray, level: LogLevel.Info);
await db.addNewTransactionData(txnsData, walletId);
// buildDateTimeChunks
final Map<String, dynamic> result = {"dateTimeChunks": <dynamic>[]};
final dateArray = <dynamic>[];
for (int i = 0; i < midSortedArray.length; i++) {
final txObject = midSortedArray[i];
final date = extractDateFromTimestamp(txObject["timestamp"] as int);
final txTimeArray = [txObject["timestamp"], date];
if (dateArray.contains(txTimeArray[1])) {
result["dateTimeChunks"].forEach((dynamic chunk) {
if (extractDateFromTimestamp(chunk["timestamp"] as int) ==
txTimeArray[1]) {
if (chunk["transactions"] == null) {
chunk["transactions"] = <Map<String, dynamic>>[];
}
chunk["transactions"].add(txObject);
}
});
} else {
dateArray.add(txTimeArray[1]);
final chunk = {
"timestamp": txTimeArray[0],
"transactions": [txObject],
};
result["dateTimeChunks"].add(chunk);
}
// quick hack to notify manager to call notifyListeners if
// transactions changed
if (txnsData.isNotEmpty) {
GlobalEventBus.instance.fire(
UpdatedInBackgroundEvent(
"Transactions updated/added for: $walletId $walletName ",
walletId,
),
);
}
// final transactionsMap = cachedTransactions?.getAllTransactions() ?? {};
final Map<String, Transaction> transactionsMap = {};
transactionsMap
.addAll(TransactionData.fromJson(result).getAllTransactions());
final txModel = TransactionData.fromMap(transactionsMap);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'storedTxnDataHeight',
// value: latestTxnBlockHeight);
// await DB.instance.put<dynamic>(
// boxName: walletId, key: 'latest_tx_model', value: txModel);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'cachedTxids',
// value: cachedTxids.toList(growable: false));
return txModel;
}
Future<String> _pathForWalletDir({
@ -1164,12 +1004,12 @@ class MoneroWallet extends CoinServiceAPI {
}
Future<void> _refreshTxData() async {
final txnData = await _fetchTransactionData();
final count = txnData.getAllTransactions().length;
await _refreshTransactions();
final count = await db.getTransactions(walletId).count();
if (count > _txCount) {
_txCount = count;
_transactionData = Future(() => txnData);
await _updateBalance();
GlobalEventBus.instance.fire(
UpdatedInBackgroundEvent(
"New transaction data found in $walletId $walletName!",
@ -1205,6 +1045,7 @@ class MoneroWallet extends CoinServiceAPI {
if (highestPercentCached < percent) {
highestPercentCached = percent;
}
await updateCachedChainHeight(height);
GlobalEventBus.instance.fire(
RefreshPercentChangedEvent(
@ -1293,23 +1134,34 @@ class MoneroWallet extends CoinServiceAPI {
}
// Check the new receiving index
String indexKey = "receivingIndex";
final curIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
final currentReceiving = await _currentReceivingAddress;
final curIndex = currentReceiving?.derivationIndex ?? -1;
if (highestIndex >= curIndex) {
// First increment the receiving index
await _incrementAddressIndexForChain(0);
final newReceivingIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
final newReceivingIndex = curIndex + 1;
// Use new index to derive a new receiving address
final newReceivingAddress =
await _generateAddressForChain(0, newReceivingIndex);
// Add that new receiving address to the array of receiving addresses
await _addToAddressesArrayForChain(newReceivingAddress, 0);
final existing = await db
.getAddresses(walletId)
.filter()
.valueEqualTo(newReceivingAddress.value)
.findFirst();
if (existing == null) {
// Add that new change address
await db.putAddress(newReceivingAddress);
} else {
// we need to update the address
await db.updateAddress(existing, newReceivingAddress);
_currentReceivingAddress = Future(() => newReceivingAddress);
// since we updated an existing address there is a chance it has
// some tx history. To prevent address reuse we will call check again
// recursively
await _checkReceivingAddressForTransactions();
}
}
} on SocketException catch (se, s) {
Logging.instance.log(
@ -1334,4 +1186,19 @@ class MoneroWallet extends CoinServiceAPI {
key: "highestPercentCached",
value: value,
);
@override
int get storedChainHeight => getCachedChainHeight();
@override
Balance get balance => _balance ??= getCachedBalance();
Balance? _balance;
@override
Future<List<isar_models.Transaction>> get transactions =>
db.getTransactions(walletId).sortByTimestampDesc().findAll();
@override
// TODO: implement utxos
Future<List<isar_models.UTXO>> get utxos => throw UnimplementedError();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,6 @@ import 'package:cw_core/wallet_type.dart';
import 'package:cw_wownero/api/exceptions/creation_transaction_exception.dart';
import 'package:cw_wownero/api/wallet.dart';
import 'package:cw_wownero/pending_wownero_transaction.dart';
import 'package:cw_wownero/wownero_amount_format.dart';
import 'package:cw_wownero/wownero_wallet.dart';
import 'package:decimal/decimal.dart';
import 'package:flutter/foundation.dart';
@ -24,21 +23,23 @@ import 'package:flutter_libmonero/core/wallet_creation_service.dart';
import 'package:flutter_libmonero/view_model/send/output.dart'
as wownero_output;
import 'package:flutter_libmonero/wownero/wownero.dart';
import 'package:http/http.dart';
import 'package:isar/isar.dart';
import 'package:mutex/mutex.dart';
import 'package:stackwallet/db/main_db.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/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/paymint/utxo_model.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart';
import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_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/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/price.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -48,17 +49,18 @@ import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
import 'package:tuple/tuple.dart';
const int MINIMUM_CONFIRMATIONS = 10;
class WowneroWallet extends CoinServiceAPI {
final String _walletId;
final Coin _coin;
final PriceAPI _priceAPI;
final SecureStorageInterface _secureStorage;
final Prefs _prefs;
class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
late final String _walletId;
late final Coin _coin;
late final SecureStorageInterface _secureStorage;
late final Prefs _prefs;
late String _walletName;
String _walletName;
bool _shouldAutoSync = false;
bool _isConnected = false;
bool _hasCalledExit = false;
@ -71,9 +73,9 @@ class WowneroWallet extends CoinServiceAPI {
WalletCreationService? _walletCreationService;
Timer? _autoSaveTimer;
Future<String>? _currentReceivingAddress;
Future<isar_models.Address?> get _currentReceivingAddress =>
db.getAddresses(walletId).sortByDerivationIndexDesc().findFirst();
Future<FeeObject>? _feeObject;
Future<TransactionData>? _transactionData;
Mutex prepareSendMutex = Mutex();
Mutex estimateFeeMutex = Mutex();
@ -83,34 +85,29 @@ class WowneroWallet extends CoinServiceAPI {
required String walletName,
required Coin coin,
required SecureStorageInterface secureStorage,
PriceAPI? priceAPI,
Prefs? prefs,
}) : _walletId = walletId,
_walletName = walletName,
_coin = coin,
_priceAPI = priceAPI ?? PriceAPI(Client()),
_secureStorage = secureStorage,
_prefs = prefs ?? Prefs.instance;
@override
bool get isFavorite {
try {
return DB.instance.get<dynamic>(boxName: walletId, key: "isFavorite")
as bool;
} catch (e, s) {
Logging.instance.log(
"isFavorite fetch failed (returning false by default): $e\n$s",
level: LogLevel.Error);
return false;
}
MainDB? mockableOverride,
}) {
_walletId = walletId;
_walletName = walletName;
_coin = coin;
_secureStorage = secureStorage;
_prefs = prefs ?? Prefs.instance;
initCache(walletId, coin);
isarInit(mockableOverride: mockableOverride);
}
@override
set isFavorite(bool markFavorite) {
DB.instance.put<dynamic>(
boxName: walletId, key: "isFavorite", value: markFavorite);
_isFavorite = markFavorite;
updateCachedIsFavorite(markFavorite);
}
@override
bool get isFavorite => _isFavorite ??= getCachedIsFavorite();
bool? _isFavorite;
@override
bool get shouldAutoSync => _shouldAutoSync;
@ -142,23 +139,6 @@ class WowneroWallet extends CoinServiceAPI {
@override
set walletName(String newName) => _walletName = newName;
@override
// not really used for wownero
Future<List<String>> get allOwnAddresses async => [];
@override
Future<Decimal> get availableBalance async {
int runningBalance = 0;
for (final entry in walletBase!.balance!.entries) {
runningBalance += entry.value.unlockedBalance;
}
return Format.satoshisToAmount(runningBalance, coin: coin);
}
@override
// not used
Future<Decimal> get balanceMinusMaxFee => throw UnimplementedError();
@override
Coin get coin => _coin;
@ -187,8 +167,9 @@ class WowneroWallet extends CoinServiceAPI {
}
@override
Future<String> get currentReceivingAddress =>
_currentReceivingAddress ??= _getCurrentAddressForChain(0);
Future<String> get currentReceivingAddress async =>
(await _currentReceivingAddress)?.value ??
(await _generateAddressForChain(0, 0)).value;
@override
Future<int> estimateFeeFor(int satoshiAmount, int feeRate) async {
@ -260,30 +241,30 @@ class WowneroWallet extends CoinServiceAPI {
int maxUnusedAddressGap,
int maxNumberOfIndexesToCheck,
) async {
// clear blockchain info
await db.deleteWalletBlockchainData(walletId);
var restoreHeight = walletBase?.walletInfo.restoreHeight;
highestPercentCached = 0;
await walletBase?.rescan(height: restoreHeight);
await refresh();
}
@override
Future<bool> generateNewAddress() async {
try {
const String indexKey = "receivingIndex";
// First increment the receiving index
await _incrementAddressIndexForChain(0);
final newReceivingIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
final currentReceiving = await _currentReceivingAddress;
final newReceivingIndex = currentReceiving!.derivationIndex + 1;
// Use new index to derive a new receiving address
final newReceivingAddress =
await _generateAddressForChain(0, newReceivingIndex);
final newReceivingAddress = await _generateAddressForChain(
0,
newReceivingIndex,
);
// Add that new receiving address to the array of receiving addresses
await _addToAddressesArrayForChain(newReceivingAddress, 0);
// Set the new receiving address that the service
_currentReceivingAddress = Future(() => newReceivingAddress);
// Add that new receiving address
await db.putAddress(newReceivingAddress);
return true;
} catch (e, s) {
@ -303,7 +284,7 @@ class WowneroWallet extends CoinServiceAPI {
"Opening existing ${coin.prettyName} wallet $walletName...",
level: LogLevel.Info);
if ((DB.instance.get<dynamic>(boxName: walletId, key: "id")) == null) {
if (getCachedId() == null) {
//todo: check if print needed
// debugPrint("Exception was thrown");
throw Exception(
@ -315,12 +296,6 @@ class WowneroWallet extends CoinServiceAPI {
keysStorage = KeyService(_secureStorage);
await _prefs.init();
// final data =
// DB.instance.get<dynamic>(boxName: walletId, key: "latest_tx_model")
// as TransactionData?;
// if (data != null) {
// _transactionData = Future(() => data);
// }
String? password;
try {
@ -335,17 +310,6 @@ class WowneroWallet extends CoinServiceAPI {
"Opened existing ${coin.prettyName} wallet $walletName",
level: LogLevel.Info,
);
// Wallet already exists, triggers for a returning user
String indexKey = "receivingIndex";
final curIndex =
await DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(0, curIndex);
Logging.instance.log(
"wownero address in init existing: $newReceivingAddress",
level: LogLevel.Info);
_currentReceivingAddress = Future(() => newReceivingAddress);
}
@override
@ -427,42 +391,18 @@ class WowneroWallet extends CoinServiceAPI {
await walletBase?.connectToNode(
node: Node(uri: "$host:${node.port}", type: WalletType.wownero));
await walletBase?.startSync();
await DB.instance
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
// Set relevant indexes
await DB.instance
.put<dynamic>(boxName: walletId, key: "receivingIndex", value: 0);
await DB.instance
.put<dynamic>(boxName: walletId, key: "changeIndex", value: 0);
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'blocked_tx_hashes',
value: ["0xdefault"],
); // A list of transaction hashes to represent frozen utxos in wallet
// initialize address book entries
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'addressBookEntries',
value: <String, String>{});
await DB.instance
.put<dynamic>(boxName: walletId, key: "isFavorite", value: false);
await Future.wait([
updateCachedId(walletId),
updateCachedIsFavorite(false),
]);
// Generate and add addresses to relevant arrays
final initialReceivingAddress = await _generateAddressForChain(0, 0);
// final initialChangeAddress = await _generateAddressForChain(1, 0);
await _addToAddressesArrayForChain(initialReceivingAddress, 0);
// await _addToAddressesArrayForChain(initialChangeAddress, 1);
await db.putAddress(initialReceivingAddress);
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'receivingAddresses',
value: [initialReceivingAddress]);
await DB.instance
.put<dynamic>(boxName: walletId, key: "receivingIndex", value: 0);
walletBase?.close();
_currentReceivingAddress = Future(() => initialReceivingAddress);
Logging.instance
.log("initializeNew for $walletName $walletId", level: LogLevel.Info);
@ -489,10 +429,6 @@ class WowneroWallet extends CoinServiceAPI {
return data;
}
@override
// not used in wow
Future<Decimal> get pendingBalance => throw UnimplementedError();
@override
Future<Map<String, dynamic>> prepareSend({
required String address,
@ -519,17 +455,15 @@ class WowneroWallet extends CoinServiceAPI {
try {
// check for send all
bool isSendAll = false;
final balance = await availableBalance;
final satInDecimal =
Format.satoshisToAmount(satoshiAmount, coin: coin);
if (satInDecimal == balance) {
final balance = await _availableBalance;
if (satoshiAmount == balance) {
isSendAll = true;
}
Logging.instance
.log("$address $satoshiAmount $args", level: LogLevel.Info);
String amountToSend = satInDecimal
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
String amountToSend =
Format.satoshisToAmount(satoshiAmount, coin: coin)
.toStringAsFixed(Constants.decimalPlacesForCoin(coin));
Logging.instance
.log("$satoshiAmount $amountToSend", level: LogLevel.Info);
@ -667,28 +601,11 @@ class WowneroWallet extends CoinServiceAPI {
.add<WalletInfo>(boxName: WalletInfo.boxName, value: walletInfo);
walletBase?.close();
walletBase = wallet as WowneroWalletBase;
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'receivingAddresses',
value: [walletInfo.address!]);
await DB.instance
.put<dynamic>(boxName: walletId, key: "receivingIndex", value: 0);
await DB.instance
.put<dynamic>(boxName: walletId, key: "id", value: _walletId);
await DB.instance
.put<dynamic>(boxName: walletId, key: "changeIndex", value: 0);
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'blocked_tx_hashes',
value: ["0xdefault"],
); // A list of transaction hashes to represent frozen utxos in wallet
// initialize address book entries
await DB.instance.put<dynamic>(
boxName: walletId,
key: 'addressBookEntries',
value: <String, String>{});
await DB.instance
.put<dynamic>(boxName: walletId, key: "isFavorite", value: false);
await Future.wait([
updateCachedId(walletId),
updateCachedIsFavorite(false),
]);
} catch (e, s) {
//todo: come back to this
debugPrint(e.toString());
@ -733,22 +650,10 @@ class WowneroWallet extends CoinServiceAPI {
),
);
final newTxData = await _fetchTransactionData();
_transactionData = Future(() => newTxData);
await _refreshTransactions();
await _updateBalance();
await _checkCurrentReceivingAddressesForTransactions();
String indexKey = "receivingIndex";
final curIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
// Use new index to derive a new receiving address
try {
final newReceivingAddress = await _generateAddressForChain(0, curIndex);
_currentReceivingAddress = Future(() => newReceivingAddress);
} catch (e, s) {
Logging.instance.log(
"Failed to call _generateAddressForChain(0, $curIndex): $e\n$s",
level: LogLevel.Error);
}
if (walletBase?.syncStatus is SyncedSyncStatus) {
refreshMutex = false;
@ -762,16 +667,6 @@ class WowneroWallet extends CoinServiceAPI {
}
}
@override
Future<String> send({
required String toAddress,
required int amount,
Map<String, String> args = const {},
}) {
// not used for xmr
throw UnimplementedError();
}
@override
Future<bool> testNetworkConnection() async {
return await walletBase?.isConnected() ?? false;
@ -835,8 +730,32 @@ class WowneroWallet extends CoinServiceAPI {
) as int? ??
0;
@override
Future<Decimal> get totalBalance async {
Future<void> _updateBalance() async {
final total = await _totalBalance;
final available = await _availableBalance;
_balance = Balance(
coin: coin,
total: total,
spendable: available,
blockedTotal: 0,
pendingSpendable: total - available,
);
await updateCachedBalance(_balance!);
}
Future<int> get _availableBalance async {
try {
int runningBalance = 0;
for (final entry in walletBase!.balance!.entries) {
runningBalance += entry.value.unlockedBalance;
}
return runningBalance;
} catch (_) {
return 0;
}
}
Future<int> get _totalBalance async {
try {
final balanceEntries = walletBase?.balance?.entries;
if (balanceEntries != null) {
@ -845,7 +764,7 @@ class WowneroWallet extends CoinServiceAPI {
bal = bal + element.value.fullBalance;
}
await _updateCachedBalance(bal);
return Format.satoshisToAmount(bal, coin: coin);
return bal;
} else {
final transactions = walletBase!.transactionHistory!.transactions;
int transactionBalance = 0;
@ -858,21 +777,13 @@ class WowneroWallet extends CoinServiceAPI {
}
await _updateCachedBalance(transactionBalance);
return Format.satoshisToAmount(transactionBalance, coin: coin);
return transactionBalance;
}
} catch (_) {
return Format.satoshisToAmount(_getCachedBalance(), coin: coin);
return _getCachedBalance();
}
}
@override
Future<TransactionData> get transactionData =>
_transactionData ??= _fetchTransactionData();
@override
// not used for xmr
Future<List<UtxoObject>> get unspentOutputs => throw UnimplementedError();
@override
Future<void> updateNode(bool shouldRefresh) async {
final node = await _getCurrentNode();
@ -901,66 +812,23 @@ class WowneroWallet extends CoinServiceAPI {
@override
String get walletId => _walletId;
/// Returns the latest receiving/change (external/internal) address for the wallet depending on [chain]
/// and
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
Future<String> _getCurrentAddressForChain(int chain) async {
// Here, we assume that chain == 1 if it isn't 0
String arrayKey = chain == 0 ? "receivingAddresses" : "changeAddresses";
final internalChainArray = (DB.instance
.get<dynamic>(boxName: walletId, key: arrayKey)) as List<dynamic>;
return internalChainArray.last as String;
}
/// Increases the index for either the internal or external chain, depending on [chain].
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
Future<void> _incrementAddressIndexForChain(int chain) async {
// Here we assume chain == 1 if it isn't 0
String indexKey = chain == 0 ? "receivingIndex" : "changeIndex";
final newIndex =
(DB.instance.get<dynamic>(boxName: walletId, key: indexKey)) + 1;
await DB.instance
.put<dynamic>(boxName: walletId, key: indexKey, value: newIndex);
}
Future<String> _generateAddressForChain(int chain, int index) async {
Future<isar_models.Address> _generateAddressForChain(
int chain,
int index,
) async {
//
String address = walletBase!.getTransactionAddress(chain, index);
return address;
}
/// Adds [address] to the relevant chain's address array, which is determined by [chain].
/// [address] - Expects a standard native segwit address
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
Future<void> _addToAddressesArrayForChain(String address, int chain) async {
String chainArray = '';
if (chain == 0) {
chainArray = 'receivingAddresses';
} else {
chainArray = 'changeAddresses';
}
final addressArray =
DB.instance.get<dynamic>(boxName: walletId, key: chainArray);
if (addressArray == null) {
Logging.instance.log(
'Attempting to add the following to $chainArray array for chain $chain:${[
address
]}',
level: LogLevel.Info);
await DB.instance
.put<dynamic>(boxName: walletId, key: chainArray, value: [address]);
} else {
// Make a deep copy of the existing list
final List<String> newArray = [];
addressArray
.forEach((dynamic _address) => newArray.add(_address as String));
newArray.add(address); // Add the address passed into the method
await DB.instance
.put<dynamic>(boxName: walletId, key: chainArray, value: newArray);
}
return isar_models.Address(
walletId: walletId,
derivationIndex: index,
value: address,
publicKey: [],
type: isar_models.AddressType.cryptonote,
subType: chain == 0
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.change,
);
}
Future<FeeObject> _getFees() async {
@ -975,7 +843,7 @@ class WowneroWallet extends CoinServiceAPI {
);
}
Future<TransactionData> _fetchTransactionData() async {
Future<void> _refreshTransactions() async {
await walletBase!.updateTransactions();
final transactions = walletBase?.transactionHistory!.transactions;
@ -1011,121 +879,117 @@ class WowneroWallet extends CoinServiceAPI {
// }
// }
// sort thing stuff
// change to get Wownero price
final priceData =
await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency);
Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero;
final List<Map<String, dynamic>> midSortedArray = [];
final List<
Tuple4<isar_models.Transaction, List<isar_models.Output>,
List<isar_models.Input>, isar_models.Address?>> txnsData = [];
if (transactions != null) {
for (var tx in transactions.entries) {
// cachedTxids.add(tx.value.id);
Logging.instance.log(
"${tx.value.accountIndex} ${tx.value.addressIndex} ${tx.value.amount} ${tx.value.date} "
"${tx.value.direction} ${tx.value.fee} ${tx.value.height} ${tx.value.id} ${tx.value.isPending} ${tx.value.key} "
"${tx.value.recipientAddress}, ${tx.value.additionalInfo} con:${tx.value.confirmations}"
" ${tx.value.keyIndex}",
level: LogLevel.Info);
String am = wowneroAmountToString(amount: tx.value.amount!);
final worthNow = (currentPrice * Decimal.parse(am)).toStringAsFixed(2);
Map<String, dynamic> midSortedTx = {};
// // create final tx map
midSortedTx["txid"] = tx.value.id;
midSortedTx["confirmed_status"] = !tx.value.isPending &&
tx.value.confirmations != null &&
tx.value.confirmations! >= MINIMUM_CONFIRMATIONS;
midSortedTx["confirmations"] = tx.value.confirmations ?? 0;
midSortedTx["timestamp"] =
(tx.value.date.millisecondsSinceEpoch ~/ 1000);
midSortedTx["txType"] =
tx.value.direction == TransactionDirection.incoming
? "Received"
: "Sent";
midSortedTx["amount"] = tx.value.amount;
midSortedTx["worthNow"] = worthNow;
midSortedTx["worthAtBlockTimestamp"] = worthNow;
midSortedTx["fees"] = tx.value.fee;
// TODO: shouldn't wownero have an address I can grab
// Logging.instance.log(
// "${tx.value.accountIndex} ${tx.value.addressIndex} ${tx.value.amount} ${tx.value.date} "
// "${tx.value.direction} ${tx.value.fee} ${tx.value.height} ${tx.value.id} ${tx.value.isPending} ${tx.value.key} "
// "${tx.value.recipientAddress}, ${tx.value.additionalInfo} con:${tx.value.confirmations}"
// " ${tx.value.keyIndex}",
// level: LogLevel.Info);
// String am = wowneroAmountToString(amount: tx.value.amount!);
// final worthNow = (currentPrice * Decimal.parse(am)).toStringAsFixed(2);
// Map<String, dynamic> midSortedTx = {};
// // // create final tx map
// midSortedTx["txid"] = tx.value.id;
// midSortedTx["confirmed_status"] = !tx.value.isPending &&
// tx.value.confirmations != null &&
// tx.value.confirmations! >= MINIMUM_CONFIRMATIONS;
// midSortedTx["confirmations"] = tx.value.confirmations ?? 0;
// midSortedTx["timestamp"] =
// (tx.value.date.millisecondsSinceEpoch ~/ 1000);
// midSortedTx["txType"] =
// tx.value.direction == TransactionDirection.incoming
// ? "Received"
// : "Sent";
// midSortedTx["amount"] = tx.value.amount;
// midSortedTx["worthNow"] = worthNow;
// midSortedTx["worthAtBlockTimestamp"] = worthNow;
// midSortedTx["fees"] = tx.value.fee;
// if (tx.value.direction == TransactionDirection.incoming) {
// final addressInfo = tx.value.additionalInfo;
//
// midSortedTx["address"] = walletBase?.getTransactionAddress(
// addressInfo!['accountIndex'] as int,
// addressInfo['addressIndex'] as int,
// );
// } else {
// midSortedTx["address"] = "";
// }
//
// final int txHeight = tx.value.height ?? 0;
// midSortedTx["height"] = txHeight;
// // if (txHeight >= latestTxnBlockHeight) {
// // latestTxnBlockHeight = txHeight;
// // }
//
// midSortedTx["aliens"] = <dynamic>[];
// midSortedTx["inputSize"] = 0;
// midSortedTx["outputSize"] = 0;
// midSortedTx["inputs"] = <dynamic>[];
// midSortedTx["outputs"] = <dynamic>[];
// midSortedArray.add(midSortedTx);
isar_models.Address? address;
isar_models.TransactionType type;
if (tx.value.direction == TransactionDirection.incoming) {
final addressInfo = tx.value.additionalInfo;
midSortedTx["address"] = walletBase?.getTransactionAddress(
final addressString = walletBase?.getTransactionAddress(
addressInfo!['accountIndex'] as int,
addressInfo['addressIndex'] as int,
);
if (addressString != null) {
address = await db
.getAddresses(walletId)
.filter()
.valueEqualTo(addressString)
.findFirst();
}
type = isar_models.TransactionType.incoming;
} else {
midSortedTx["address"] = "";
// txn.address = "";
type = isar_models.TransactionType.outgoing;
}
final int txHeight = tx.value.height ?? 0;
midSortedTx["height"] = txHeight;
// if (txHeight >= latestTxnBlockHeight) {
// latestTxnBlockHeight = txHeight;
// }
final txn = isar_models.Transaction(
walletId: walletId,
txid: tx.value.id,
timestamp: (tx.value.date.millisecondsSinceEpoch ~/ 1000),
type: type,
subType: isar_models.TransactionSubType.none,
amount: tx.value.amount ?? 0,
fee: tx.value.fee ?? 0,
height: tx.value.height,
isCancelled: false,
isLelantus: false,
slateId: null,
otherData: null,
);
midSortedTx["aliens"] = <dynamic>[];
midSortedTx["inputSize"] = 0;
midSortedTx["outputSize"] = 0;
midSortedTx["inputs"] = <dynamic>[];
midSortedTx["outputs"] = <dynamic>[];
midSortedArray.add(midSortedTx);
txnsData.add(Tuple4(txn, [], [], address));
}
}
// sort by date ----
midSortedArray
.sort((a, b) => (b["timestamp"] as int) - (a["timestamp"] as int));
Logging.instance.log(midSortedArray, level: LogLevel.Info);
await db.addNewTransactionData(txnsData, walletId);
// buildDateTimeChunks
final Map<String, dynamic> result = {"dateTimeChunks": <dynamic>[]};
final dateArray = <dynamic>[];
for (int i = 0; i < midSortedArray.length; i++) {
final txObject = midSortedArray[i];
final date = extractDateFromTimestamp(txObject["timestamp"] as int);
final txTimeArray = [txObject["timestamp"], date];
if (dateArray.contains(txTimeArray[1])) {
result["dateTimeChunks"].forEach((dynamic chunk) {
if (extractDateFromTimestamp(chunk["timestamp"] as int) ==
txTimeArray[1]) {
if (chunk["transactions"] == null) {
chunk["transactions"] = <Map<String, dynamic>>[];
}
chunk["transactions"].add(txObject);
}
});
} else {
dateArray.add(txTimeArray[1]);
final chunk = {
"timestamp": txTimeArray[0],
"transactions": [txObject],
};
result["dateTimeChunks"].add(chunk);
}
// quick hack to notify manager to call notifyListeners if
// transactions changed
if (txnsData.isNotEmpty) {
GlobalEventBus.instance.fire(
UpdatedInBackgroundEvent(
"Transactions updated/added for: $walletId $walletName ",
walletId,
),
);
}
// final transactionsMap = cachedTransactions?.getAllTransactions() ?? {};
final Map<String, Transaction> transactionsMap = {};
transactionsMap
.addAll(TransactionData.fromJson(result).getAllTransactions());
final txModel = TransactionData.fromMap(transactionsMap);
//
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'storedTxnDataHeight',
// value: latestTxnBlockHeight);
// await DB.instance.put<dynamic>(
// boxName: walletId, key: 'latest_tx_model', value: txModel);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'cachedTxids',
// value: cachedTxids.toList(growable: false));
return txModel;
}
Future<String> _pathForWalletDir({
@ -1193,12 +1057,12 @@ class WowneroWallet extends CoinServiceAPI {
}
Future<void> _refreshTxData() async {
final txnData = await _fetchTransactionData();
final count = txnData.getAllTransactions().length;
await _refreshTransactions();
final count = await db.getTransactions(walletId).count();
if (count > _txCount) {
_txCount = count;
_transactionData = Future(() => txnData);
await _updateBalance();
GlobalEventBus.instance.fire(
UpdatedInBackgroundEvent(
"New transaction data found in $walletId $walletName!",
@ -1249,6 +1113,7 @@ class WowneroWallet extends CoinServiceAPI {
if (highestPercentCached < percent) {
highestPercentCached = percent;
}
await updateCachedChainHeight(height);
GlobalEventBus.instance.fire(
RefreshPercentChangedEvent(
@ -1337,23 +1202,34 @@ class WowneroWallet extends CoinServiceAPI {
}
// Check the new receiving index
String indexKey = "receivingIndex";
final curIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
final currentReceiving = await _currentReceivingAddress;
final curIndex = currentReceiving?.derivationIndex ?? -1;
if (highestIndex >= curIndex) {
// First increment the receiving index
await _incrementAddressIndexForChain(0);
final newReceivingIndex =
DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
final newReceivingIndex = curIndex + 1;
// Use new index to derive a new receiving address
final newReceivingAddress =
await _generateAddressForChain(0, newReceivingIndex);
// Add that new receiving address to the array of receiving addresses
await _addToAddressesArrayForChain(newReceivingAddress, 0);
final existing = await db
.getAddresses(walletId)
.filter()
.valueEqualTo(newReceivingAddress.value)
.findFirst();
if (existing == null) {
// Add that new change address
await db.putAddress(newReceivingAddress);
} else {
// we need to update the address
await db.updateAddress(existing, newReceivingAddress);
_currentReceivingAddress = Future(() => newReceivingAddress);
// since we updated an existing address there is a chance it has
// some tx history. To prevent address reuse we will call check again
// recursively
await _checkReceivingAddressForTransactions();
}
}
} on SocketException catch (se, s) {
Logging.instance.log(
@ -1378,4 +1254,19 @@ class WowneroWallet extends CoinServiceAPI {
key: "highestPercentCached",
value: value,
);
@override
int get storedChainHeight => getCachedChainHeight();
@override
Balance get balance => _balance ??= getCachedBalance();
Balance? _balance;
@override
Future<List<isar_models.Transaction>> get transactions =>
db.getTransactions(walletId).sortByTimestampDesc().findAll();
@override
// TODO: implement utxos
Future<List<isar_models.UTXO>> get utxos => throw UnimplementedError();
}

View file

@ -0,0 +1,112 @@
import 'package:stackwallet/hive/db.dart';
mixin EpicCashHive {
late final String _walletId;
void initEpicCashHive(String walletId) {
_walletId = walletId;
}
// receiving index
int? epicGetReceivingIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "receivingIndex")
as int?;
}
Future<void> epicUpdateReceivingIndex(int index) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "receivingIndex",
value: index,
);
}
// change index
int? epicGetChangeIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "changeIndex")
as int?;
}
Future<void> epicUpdateChangeIndex(int index) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "changeIndex",
value: index,
);
}
// slateToAddresses
Map epicGetSlatesToAddresses() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: "slate_to_address",
) as Map? ??
{};
}
Future<void> epicUpdateSlatesToAddresses(Map map) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "slate_to_address",
value: map,
);
}
// slatesToCommits
Map? epicGetSlatesToCommits() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: "slatesToCommits",
) as Map?;
}
Future<void> epicUpdateSlatesToCommits(Map map) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "slatesToCommits",
value: map,
);
}
// last scanned block
int? epicGetLastScannedBlock() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "lastScannedBlock")
as int?;
}
Future<void> epicUpdateLastScannedBlock(int blockHeight) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "lastScannedBlock",
value: blockHeight,
);
}
// epic restore height
int? epicGetRestoreHeight() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "restoreHeight")
as int?;
}
Future<void> epicUpdateRestoreHeight(int height) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "restoreHeight",
value: height,
);
}
// epic creation height
int? epicGetCreationHeight() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "creationHeight")
as int?;
}
Future<void> epicUpdateCreationHeight(int height) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "creationHeight",
value: height,
);
}
}

View file

@ -0,0 +1,50 @@
import 'package:stackwallet/hive/db.dart';
mixin FiroHive {
late final String _walletId;
void initFiroHive(String walletId) {
_walletId = walletId;
}
// jindex
List? firoGetJIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "jindex") as List?;
}
Future<void> firoUpdateJIndex(List jIndex) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "jindex",
value: jIndex,
);
}
// _lelantus_coins
List? firoGetLelantusCoins() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "_lelantus_coins")
as List?;
}
Future<void> firoUpdateLelantusCoins(List lelantusCoins) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "_lelantus_coins",
value: lelantusCoins,
);
}
// mintIndex
int? firoGetMintIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "mintIndex")
as int?;
}
Future<void> firoUpdateMintIndex(int mintIndex) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "mintIndex",
value: mintIndex,
);
}
}

View file

@ -0,0 +1,115 @@
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
mixin WalletCache {
late final String _walletId;
late final Coin _coin;
void initCache(String walletId, Coin coin) {
_walletId = walletId;
_coin = coin;
}
// cached wallet id
String? getCachedId() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: DBKeys.id,
) as String?;
}
Future<void> updateCachedId(String? id) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: DBKeys.id,
value: id,
);
}
// cached Chain Height
int getCachedChainHeight() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: DBKeys.storedChainHeight,
) as int? ??
0;
}
Future<void> updateCachedChainHeight(int height) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: DBKeys.storedChainHeight,
value: height,
);
}
// wallet favorite flag
bool getCachedIsFavorite() {
return DB.instance.get<dynamic>(
boxName: _walletId,
key: DBKeys.isFavorite,
) as bool? ??
false;
}
Future<void> updateCachedIsFavorite(bool isFavorite) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: DBKeys.isFavorite,
value: isFavorite,
);
}
// main balance cache
Balance getCachedBalance() {
final jsonString = DB.instance.get<dynamic>(
boxName: _walletId,
key: DBKeys.cachedBalance,
) as String?;
if (jsonString == null) {
return Balance(
coin: _coin,
total: 0,
spendable: 0,
blockedTotal: 0,
pendingSpendable: 0,
);
}
return Balance.fromJson(jsonString, _coin);
}
Future<void> updateCachedBalance(Balance balance) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: DBKeys.cachedBalance,
value: balance.toJsonIgnoreCoin(),
);
}
// secondary balance cache for coins such as firo
Balance getCachedBalanceSecondary() {
final jsonString = DB.instance.get<dynamic>(
boxName: _walletId,
key: DBKeys.cachedBalanceSecondary,
) as String?;
if (jsonString == null) {
return Balance(
coin: _coin,
total: 0,
spendable: 0,
blockedTotal: 0,
pendingSpendable: 0,
);
}
return Balance.fromJson(jsonString, _coin);
}
Future<void> updateCachedBalanceSecondary(Balance balance) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: DBKeys.cachedBalanceSecondary,
value: balance.toJsonIgnoreCoin(),
);
}
}

View file

@ -0,0 +1,10 @@
import 'package:stackwallet/db/main_db.dart';
mixin WalletDB {
MainDB? _db;
MainDB get db => _db!;
void isarInit({MainDB? mockableOverride}) async {
_db = mockableOverride ?? MainDB.instance;
}
}

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/wownero/wownero.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
import 'package:stackwallet/services/notifications_service.dart';
@ -385,6 +386,9 @@ class WalletsService extends ChangeNotifier {
level: LogLevel.Info);
}
// delete wallet data in main db
await MainDB.instance.deleteWalletBlockchainData(walletId);
// box data may currently still be read/written to if wallet was refreshing
// when delete was requested so instead of deleting now we mark the wallet
// as needs delete by adding it's id to a list which gets checked on app start

View file

@ -20,9 +20,14 @@ class AddressUtils {
/// attempts to convert a string to a valid scripthash
///
/// Returns the scripthash or throws an exception on invalid firo address
static String convertToScriptHash(String address, NetworkType network) {
static String convertToScriptHash(
String address,
NetworkType network, [
String overridePrefix = "",
]) {
try {
final output = Address.addressToOutputScript(address, network);
final output =
Address.addressToOutputScript(address, network, overridePrefix);
final hash = sha256.convert(output.toList(growable: false)).toString();
final chars = hash.split("");

View file

@ -38,7 +38,7 @@ abstract class Constants {
// Enable Logger.print statements
static const bool disableLogger = false;
static const int currentHiveDbVersion = 4;
static const int currentHiveDbVersion = 5;
static int satsPerCoin(Coin coin) {
switch (coin) {

View file

@ -1,19 +1,25 @@
import 'dart:convert';
import 'package:hive/hive.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/lelantus_coin.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/models.dart';
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/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';
class DbVersionMigrator {
class DbVersionMigrator with WalletDB {
Future<void> migrate(
int fromVersion, {
required SecureStorageInterface secureStore,
@ -169,9 +175,398 @@ class DbVersionMigrator {
// try to continue migrating
return await migrate(4, secureStore: secureStore);
case 4:
// migrate
await _v4(secureStore);
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 5);
// try to continue migrating
return await migrate(5, secureStore: secureStore);
default:
// finally return
return;
}
}
Future<void> _v4(SecureStorageInterface secureStore) async {
await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
await Hive.openBox<dynamic>(DB.boxNamePrefs);
final walletsService = WalletsService(secureStorageInterface: secureStore);
final prefs = Prefs.instance;
final walletInfoList = await walletsService.walletNames;
await prefs.init();
for (final walletId in walletInfoList.keys) {
final info = walletInfoList[walletId]!;
assert(info.walletId == walletId);
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");
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");
// 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<isar_models.Address> newAddresses = [];
if (p2pkhRcvDerivations != null) {
newAddresses.addAll(
_v4GetAddressesFromDerivationString(
p2pkhRcvDerivations,
isar_models.AddressType.p2pkh,
isar_models.AddressSubType.receiving,
walletId,
),
);
}
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);
}
}
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<
Tuple4<
isar_models.Transaction,
List<isar_models.Output>,
List<isar_models.Input>,
isar_models.Address?>> newTransactions = [];
newTransactions
.addAll(_parseTransactions(txns, walletId, false, newAddresses));
newTransactions.addAll(
_parseTransactions(txnsLelantus, walletId, true, newAddresses));
// store newly parsed data in isar
isarInit();
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");
await walletBox.delete("${receiveAddressesPrefix}P2SH");
await walletBox.delete("${receiveAddressesPrefix}P2WPKH");
await walletBox.delete(changeAddressesPrefix);
await walletBox.delete("${changeAddressesPrefix}P2PKH");
await walletBox.delete("${changeAddressesPrefix}P2SH");
await walletBox.delete("${changeAddressesPrefix}P2WPKH");
await walletBox.delete("latest_tx_model");
await walletBox.delete("latest_lelantus_tx_model");
}
}
List<
Tuple4<isar_models.Transaction, List<isar_models.Output>,
List<isar_models.Input>, isar_models.Address?>> _parseTransactions(
Iterable<Transaction> txns,
String walletId,
bool isLelantus,
List<isar_models.Address> parsedAddresses,
) {
List<
Tuple4<isar_models.Transaction, List<isar_models.Output>,
List<isar_models.Input>, 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;
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,
);
final List<isar_models.Input> inputs = [];
final List<isar_models.Output> outputs = [];
for (final inp in tx.inputs) {
final input = isar_models.Input(
walletId: walletId,
txid: inp.txid,
vout: inp.vout,
scriptSig: inp.scriptsig,
scriptSigAsm: inp.scriptsigAsm,
isCoinbase: inp.isCoinbase,
sequence: inp.sequence,
innerRedeemScriptAsm: inp.innerRedeemscriptAsm,
);
inputs.add(input);
}
for (final out in tx.outputs) {
final output = isar_models.Output(
walletId: walletId,
scriptPubKey: out.scriptpubkey,
scriptPubKeyAsm: out.scriptpubkeyAsm,
scriptPubKeyType: out.scriptpubkeyType,
scriptPubKeyAddress: out.scriptpubkeyAddress,
value: out.value,
);
outputs.add(output);
}
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,
type: isar_models.AddressType.unknown,
subType: type == isar_models.TransactionType.incoming
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.change,
);
}
}
transactions.add(Tuple4(transaction, outputs, inputs, 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,
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,
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

@ -158,7 +158,7 @@ abstract class DefaultNodes {
isDown: false);
static NodeModel get bitcoinTestnet => NodeModel(
host: "bitcoin-testnet.cypherstack.com",
host: "bitcoin-testnet.stackwallet.com",
port: 51002,
name: defaultName,
id: _nodeId(Coin.bitcoinTestNet),

View file

@ -190,7 +190,8 @@ extension CoinExt on Coin {
case Coin.dogecoin:
case Coin.dogecoinTestNet:
return true;
// return true;
return false;
}
}

View file

@ -1,13 +1,8 @@
import 'package:isar/isar.dart';
// Used in Isar db and stored there as int indexes so adding/removing values
// in this definition should be done extremely carefully in production
enum LogLevel with IsarEnum<String> {
enum LogLevel {
Info,
Warning,
Error,
Fatal;
@override
String get value => name;
}

View file

@ -49,9 +49,16 @@ class Logging {
Logger.print(object, normalLength: !printFullLength);
return;
}
String message = object.toString();
// random value to check max size of message before storing in db
if (message.length > 20000) {
message = "${message.substring(0, 20000)}...";
}
final now = core.DateTime.now().toUtc();
final log = Log()
..message = object.toString()
..message = message
..logLevel = level
..timestampInMillisUTC = now.millisecondsSinceEpoch;
if (level == LogLevel.Error || level == LogLevel.Fatal) {

View file

@ -105,7 +105,7 @@ class _ManagedFavoriteCardState extends ConsumerState<ManagedFavorite> {
Expanded(
child: Text(
"${Format.localizedStringAsFixed(
value: manager.cachedTotalBalance,
value: manager.balance.getTotal(),
locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) => value.locale)),
@ -147,7 +147,7 @@ class _ManagedFavoriteCardState extends ConsumerState<ManagedFavorite> {
),
Text(
"${Format.localizedStringAsFixed(
value: manager.cachedTotalBalance,
value: manager.balance.getTotal(),
locale: ref.watch(localeServiceChangeNotifierProvider
.select((value) => value.locale)),
decimalPlaces: 8,

View file

@ -2,10 +2,11 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart';
import 'package:stackwallet/providers/blockchain/dogecoin/current_height_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -34,14 +35,24 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
late final Transaction _transaction;
late final String walletId;
String whatIsIt(String type, Coin coin) {
String whatIsIt(
TransactionType type,
Coin coin,
int currentHeight,
) {
if (coin == Coin.epicCash && _transaction.slateId == null) {
return "Restored Funds";
}
if (_transaction.subType == "mint") {
final confirmedStatus = _transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
);
if (type != TransactionType.incoming &&
_transaction.subType == TransactionSubType.mint) {
// if (type == "Received") {
if (_transaction.confirmedStatus) {
if (confirmedStatus) {
return "Anonymized";
} else {
return "Anonymizing";
@ -57,23 +68,23 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
// }
}
if (type == "Received") {
if (type == TransactionType.incoming) {
// if (_transaction.isMinting) {
// return "Minting";
// } else
if (_transaction.confirmedStatus) {
if (confirmedStatus) {
return "Received";
} else {
return "Receiving";
}
} else if (type == "Sent") {
if (_transaction.confirmedStatus) {
} else if (type == TransactionType.outgoing) {
if (confirmedStatus) {
return "Sent";
} else {
return "Sending";
}
} else {
return type;
return type.name;
}
}
@ -103,13 +114,15 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
String prefix = "";
if (Util.isDesktop) {
if (_transaction.txType == "Sent") {
if (_transaction.type == TransactionType.outgoing) {
prefix = "-";
} else if (_transaction.txType == "Received") {
} else if (_transaction.type == TransactionType.incoming) {
prefix = "+";
}
}
final currentHeight = ref.watch(currentHeightProvider(coin).state).state;
return Material(
color: Theme.of(context).extension<StackColors>()!.popupBG,
elevation: 0,
@ -166,7 +179,12 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
padding: const EdgeInsets.all(8),
child: Row(
children: [
TxIcon(transaction: _transaction),
TxIcon(
transaction: _transaction,
coin: ref.watch(walletsChangeNotifierProvider.select(
(value) => value.getManager(widget.walletId).coin)),
currentHeight: currentHeight,
),
const SizedBox(
width: 14,
),
@ -184,7 +202,11 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
child: Text(
_transaction.isCancelled
? "Cancelled"
: whatIsIt(_transaction.txType, coin),
: whatIsIt(
_transaction.type,
coin,
currentHeight,
),
style: STextStyles.itemSubtitle12(context),
),
),

View file

@ -27,8 +27,9 @@ class WalletInfoRowBalanceFuture extends ConsumerWidget {
),
);
// TODO redo this widget now that its not actually a future
return FutureBuilder(
future: manager.totalBalance,
future: Future(() => manager.balance.getTotal()),
builder: (builderContext, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {

View file

@ -803,21 +803,21 @@ packages:
name: isar
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0-dev.10"
version: "3.0.5"
isar_flutter_libs:
dependency: "direct main"
description:
name: isar_flutter_libs
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0-dev.10"
version: "3.0.5"
isar_generator:
dependency: "direct dev"
description:
name: isar_generator
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0-dev.10"
version: "3.0.5"
js:
dependency: transitive
description:

View file

@ -135,8 +135,8 @@ dependencies:
file_picker: ^5.0.1
connectivity_plus: 2.3.6+1
# document_file_save_plus: ^1.0.5
isar: 3.0.0-dev.10
isar_flutter_libs: 3.0.0-dev.10 # contains the binaries
isar: 3.0.5
isar_flutter_libs: 3.0.5 # contains the binaries
dropdown_button2: 1.7.2
string_validator: ^0.3.0
@ -156,7 +156,7 @@ dev_dependencies:
analyzer: ^4.6.0
import_sorter: ^4.6.0
flutter_lints: ^2.0.1
isar_generator: 3.0.0-dev.10
isar_generator: 3.0.5
flutter_icons:
android: true

View file

@ -17,6 +17,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/theme/light_colors.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'send_view_test.mocks.dart';
@GenerateMocks([
@ -84,6 +85,8 @@ void main() {
),
);
await widgetTester.pumpAndSettle();
expect(find.text("Send to"), findsOneWidget);
expect(find.text("Amount"), findsOneWidget);
expect(find.text("Note (optional)"), findsOneWidget);
@ -147,6 +150,8 @@ void main() {
),
);
await widgetTester.pumpAndSettle();
expect(find.text("Send to"), findsOneWidget);
expect(find.text("Amount"), findsOneWidget);
expect(find.text("Note (optional)"), findsOneWidget);

File diff suppressed because it is too large Load diff

View file

@ -7,9 +7,10 @@ import 'dart:async' as _i8;
import 'dart:ui' as _i10;
import 'package:barcode_scan2/barcode_scan2.dart' as _i2;
import 'package:decimal/decimal.dart' as _i6;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i6;
import 'package:stackwallet/models/contact.dart' as _i3;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i13;
import 'package:stackwallet/models/models.dart' as _i5;
import 'package:stackwallet/services/address_book_service.dart' as _i9;
import 'package:stackwallet/services/coins/coin_service.dart' as _i4;
@ -69,19 +70,8 @@ class _FakeFeeObject_3 extends _i1.SmartFake implements _i5.FeeObject {
);
}
class _FakeDecimal_4 extends _i1.SmartFake implements _i6.Decimal {
_FakeDecimal_4(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_5 extends _i1.SmartFake
implements _i5.TransactionData {
_FakeTransactionData_5(
class _FakeBalance_4 extends _i1.SmartFake implements _i6.Balance {
_FakeBalance_4(
Object parent,
Invocation parentInvocation,
) : super(
@ -321,72 +311,24 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<_i6.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i8.Future<_i6.Decimal>.value(_FakeDecimal_4(
_i6.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_4(
this,
Invocation.getter(#availableBalance),
)),
) as _i8.Future<_i6.Decimal>);
@override
_i6.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_4(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i6.Decimal);
) as _i6.Balance);
@override
_i8.Future<_i6.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i8.Future<_i6.Decimal>.value(_FakeDecimal_4(
this,
Invocation.getter(#pendingBalance),
)),
) as _i8.Future<_i6.Decimal>);
@override
_i8.Future<_i6.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i8.Future<_i6.Decimal>.value(_FakeDecimal_4(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i8.Future<_i6.Decimal>);
@override
_i8.Future<_i6.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i8.Future<_i6.Decimal>.value(_FakeDecimal_4(
this,
Invocation.getter(#totalBalance),
)),
) as _i8.Future<_i6.Decimal>);
@override
_i6.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_4(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i6.Decimal);
@override
_i8.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i8.Future<List<String>>.value(<String>[]),
) as _i8.Future<List<String>>);
@override
_i8.Future<_i5.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i8.Future<List<_i13.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i8.Future<_i5.TransactionData>.value(_FakeTransactionData_5(
this,
Invocation.getter(#transactionData),
)),
) as _i8.Future<_i5.TransactionData>);
_i8.Future<List<_i13.Transaction>>.value(<_i13.Transaction>[]),
) as _i8.Future<List<_i13.Transaction>>);
@override
_i8.Future<List<_i5.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i8.Future<List<_i5.UtxoObject>>.value(<_i5.UtxoObject>[]),
) as _i8.Future<List<_i5.UtxoObject>>);
_i8.Future<List<_i13.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i8.Future<List<_i13.UTXO>>.value(<_i13.UTXO>[]),
) as _i8.Future<List<_i13.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -416,6 +358,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -467,24 +414,6 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -574,14 +503,6 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i8.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -6,15 +6,16 @@
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/contact.dart' as _i2;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i11;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/address_book_service.dart' as _i6;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
import 'package:stackwallet/services/coins/manager.dart' as _i9;
import 'package:stackwallet/services/locale_service.dart' as _i12;
import 'package:stackwallet/services/notes_service.dart' as _i11;
import 'package:stackwallet/services/locale_service.dart' as _i13;
import 'package:stackwallet/services/notes_service.dart' as _i12;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i10;
// ignore_for_file: type=lint
@ -59,19 +60,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -282,72 +272,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i7.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i11.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i4.TransactionData>);
_i7.Future<List<_i11.Transaction>>.value(<_i11.Transaction>[]),
) as _i7.Future<List<_i11.Transaction>>);
@override
_i7.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i7.Future<List<_i4.UtxoObject>>);
_i7.Future<List<_i11.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i11.UTXO>>.value(<_i11.UTXO>[]),
) as _i7.Future<List<_i11.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -377,6 +319,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -428,24 +375,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -535,14 +464,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -594,7 +515,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
/// A class which mocks [NotesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockNotesService extends _i1.Mock implements _i11.NotesService {
class MockNotesService extends _i1.Mock implements _i12.NotesService {
@override
String get walletId => (super.noSuchMethod(
Invocation.getter(#walletId),
@ -696,7 +617,7 @@ class MockNotesService extends _i1.Mock implements _i11.NotesService {
/// A class which mocks [LocaleService].
///
/// See the documentation for Mockito's code generation for more information.
class MockLocaleService extends _i1.Mock implements _i12.LocaleService {
class MockLocaleService extends _i1.Mock implements _i13.LocaleService {
@override
String get locale => (super.noSuchMethod(
Invocation.getter(#locale),

View file

@ -6,9 +6,10 @@
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/contact.dart' as _i2;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i11;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/address_book_service.dart' as _i6;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
@ -57,19 +58,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -280,72 +270,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i7.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i11.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i4.TransactionData>);
_i7.Future<List<_i11.Transaction>>.value(<_i11.Transaction>[]),
) as _i7.Future<List<_i11.Transaction>>);
@override
_i7.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i7.Future<List<_i4.UtxoObject>>);
_i7.Future<List<_i11.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i11.UTXO>>.value(<_i11.UTXO>[]),
) as _i7.Future<List<_i11.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -375,6 +317,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -426,24 +373,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -533,14 +462,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -423,6 +423,11 @@ class MockTradesService extends _i1.Mock implements _i9.TradesService {
returnValue: false,
) as bool);
@override
_i10.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method(
#get,
[tradeId],
)) as _i10.Trade?);
@override
_i7.Future<void> add({
required _i10.Trade? trade,
required bool? shouldNotifyListeners,

View file

@ -6,8 +6,9 @@
import 'dart:async' as _i7;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i13;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/models/node_model.dart' as _i11;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
@ -61,19 +62,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -589,72 +579,24 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i7.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i13.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i4.TransactionData>);
_i7.Future<List<_i13.Transaction>>.value(<_i13.Transaction>[]),
) as _i7.Future<List<_i13.Transaction>>);
@override
_i7.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i7.Future<List<_i4.UtxoObject>>);
_i7.Future<List<_i13.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i13.UTXO>>.value(<_i13.UTXO>[]),
) as _i7.Future<List<_i13.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -684,6 +626,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -735,24 +682,6 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -842,14 +771,6 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -6,13 +6,14 @@
import 'dart:async' as _i6;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i10;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i9;
import 'package:stackwallet/services/locale_service.dart' as _i11;
import 'package:stackwallet/services/notes_service.dart' as _i10;
import 'package:stackwallet/services/locale_service.dart' as _i12;
import 'package:stackwallet/services/notes_service.dart' as _i11;
import 'package:stackwallet/services/wallets_service.dart' as _i5;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i7;
@ -48,19 +49,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -376,72 +366,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i6.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i6.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i6.Future<List<String>>.value(<String>[]),
) as _i6.Future<List<String>>);
@override
_i6.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i6.Future<List<_i10.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i6.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i6.Future<_i3.TransactionData>);
_i6.Future<List<_i10.Transaction>>.value(<_i10.Transaction>[]),
) as _i6.Future<List<_i10.Transaction>>);
@override
_i6.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i6.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i6.Future<List<_i3.UtxoObject>>);
_i6.Future<List<_i10.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i6.Future<List<_i10.UTXO>>.value(<_i10.UTXO>[]),
) as _i6.Future<List<_i10.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -471,6 +413,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -522,24 +469,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -629,14 +558,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -688,7 +609,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
/// A class which mocks [NotesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockNotesService extends _i1.Mock implements _i10.NotesService {
class MockNotesService extends _i1.Mock implements _i11.NotesService {
@override
String get walletId => (super.noSuchMethod(
Invocation.getter(#walletId),
@ -790,7 +711,7 @@ class MockNotesService extends _i1.Mock implements _i10.NotesService {
/// A class which mocks [LocaleService].
///
/// See the documentation for Mockito's code generation for more information.
class MockLocaleService extends _i1.Mock implements _i11.LocaleService {
class MockLocaleService extends _i1.Mock implements _i12.LocaleService {
@override
String get locale => (super.noSuchMethod(
Invocation.getter(#locale),

View file

@ -6,13 +6,14 @@
import 'dart:async' as _i6;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i10;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i9;
import 'package:stackwallet/services/locale_service.dart' as _i11;
import 'package:stackwallet/services/notes_service.dart' as _i10;
import 'package:stackwallet/services/locale_service.dart' as _i12;
import 'package:stackwallet/services/notes_service.dart' as _i11;
import 'package:stackwallet/services/wallets_service.dart' as _i5;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i7;
@ -48,19 +49,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -376,72 +366,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i6.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i6.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i6.Future<List<String>>.value(<String>[]),
) as _i6.Future<List<String>>);
@override
_i6.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i6.Future<List<_i10.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i6.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i6.Future<_i3.TransactionData>);
_i6.Future<List<_i10.Transaction>>.value(<_i10.Transaction>[]),
) as _i6.Future<List<_i10.Transaction>>);
@override
_i6.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i6.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i6.Future<List<_i3.UtxoObject>>);
_i6.Future<List<_i10.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i6.Future<List<_i10.UTXO>>.value(<_i10.UTXO>[]),
) as _i6.Future<List<_i10.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -471,6 +413,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -522,24 +469,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -629,14 +558,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -688,7 +609,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
/// A class which mocks [NotesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockNotesService extends _i1.Mock implements _i10.NotesService {
class MockNotesService extends _i1.Mock implements _i11.NotesService {
@override
String get walletId => (super.noSuchMethod(
Invocation.getter(#walletId),
@ -790,7 +711,7 @@ class MockNotesService extends _i1.Mock implements _i10.NotesService {
/// A class which mocks [LocaleService].
///
/// See the documentation for Mockito's code generation for more information.
class MockLocaleService extends _i1.Mock implements _i11.LocaleService {
class MockLocaleService extends _i1.Mock implements _i12.LocaleService {
@override
String get locale => (super.noSuchMethod(
Invocation.getter(#locale),

View file

@ -6,13 +6,14 @@
import 'dart:async' as _i6;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i10;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i9;
import 'package:stackwallet/services/locale_service.dart' as _i11;
import 'package:stackwallet/services/notes_service.dart' as _i10;
import 'package:stackwallet/services/locale_service.dart' as _i12;
import 'package:stackwallet/services/notes_service.dart' as _i11;
import 'package:stackwallet/services/wallets_service.dart' as _i5;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i7;
@ -48,19 +49,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -376,72 +366,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i6.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i6.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i6.Future<List<String>>.value(<String>[]),
) as _i6.Future<List<String>>);
@override
_i6.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i6.Future<List<_i10.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i6.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i6.Future<_i3.TransactionData>);
_i6.Future<List<_i10.Transaction>>.value(<_i10.Transaction>[]),
) as _i6.Future<List<_i10.Transaction>>);
@override
_i6.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i6.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i6.Future<List<_i3.UtxoObject>>);
_i6.Future<List<_i10.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i6.Future<List<_i10.UTXO>>.value(<_i10.UTXO>[]),
) as _i6.Future<List<_i10.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -471,6 +413,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -522,24 +469,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -629,14 +558,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -688,7 +609,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
/// A class which mocks [NotesService].
///
/// See the documentation for Mockito's code generation for more information.
class MockNotesService extends _i1.Mock implements _i10.NotesService {
class MockNotesService extends _i1.Mock implements _i11.NotesService {
@override
String get walletId => (super.noSuchMethod(
Invocation.getter(#walletId),
@ -790,7 +711,7 @@ class MockNotesService extends _i1.Mock implements _i10.NotesService {
/// A class which mocks [LocaleService].
///
/// See the documentation for Mockito's code generation for more information.
class MockLocaleService extends _i1.Mock implements _i11.LocaleService {
class MockLocaleService extends _i1.Mock implements _i12.LocaleService {
@override
String get locale => (super.noSuchMethod(
Invocation.getter(#locale),

View file

@ -4,10 +4,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i8;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i5;
@ -45,19 +46,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -151,72 +141,24 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i7.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i8.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i3.TransactionData>);
_i7.Future<List<_i8.Transaction>>.value(<_i8.Transaction>[]),
) as _i7.Future<List<_i8.Transaction>>);
@override
_i7.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i7.Future<List<_i3.UtxoObject>>);
_i7.Future<List<_i8.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i8.UTXO>>.value(<_i8.UTXO>[]),
) as _i7.Future<List<_i8.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -246,6 +188,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -297,24 +244,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -404,14 +333,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -435,7 +356,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -443,7 +364,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -6,8 +6,9 @@
import 'dart:async' as _i6;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i10;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i9;
@ -46,19 +47,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -374,72 +364,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i6.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i6.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i6.Future<List<String>>.value(<String>[]),
) as _i6.Future<List<String>>);
@override
_i6.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i6.Future<List<_i10.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i6.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i6.Future<_i3.TransactionData>);
_i6.Future<List<_i10.Transaction>>.value(<_i10.Transaction>[]),
) as _i6.Future<List<_i10.Transaction>>);
@override
_i6.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i6.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i6.Future<List<_i3.UtxoObject>>);
_i6.Future<List<_i10.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i6.Future<List<_i10.UTXO>>.value(<_i10.UTXO>[]),
) as _i6.Future<List<_i10.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -469,6 +411,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -520,24 +467,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -627,14 +556,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -6,8 +6,9 @@
import 'dart:async' as _i7;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i13;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/models/node_model.dart' as _i11;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
@ -61,19 +62,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -589,72 +579,24 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i7.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i7.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i13.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i4.TransactionData>);
_i7.Future<List<_i13.Transaction>>.value(<_i13.Transaction>[]),
) as _i7.Future<List<_i13.Transaction>>);
@override
_i7.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i7.Future<List<_i4.UtxoObject>>);
_i7.Future<List<_i13.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i13.UTXO>>.value(<_i13.UTXO>[]),
) as _i7.Future<List<_i13.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -684,6 +626,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -735,24 +682,6 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -842,14 +771,6 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -7,13 +7,14 @@ import 'dart:async' as _i8;
import 'dart:ui' as _i11;
import 'package:barcode_scan2/barcode_scan2.dart' as _i2;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i13;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/models/node_model.dart' as _i14;
import 'package:stackwallet/models/node_model.dart' as _i15;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
import 'package:stackwallet/services/coins/manager.dart' as _i12;
import 'package:stackwallet/services/node_service.dart' as _i13;
import 'package:stackwallet/services/node_service.dart' as _i14;
import 'package:stackwallet/services/wallets_service.dart' as _i9;
import 'package:stackwallet/utilities/barcode_scanner_interface.dart' as _i7;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i10;
@ -62,8 +63,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -72,20 +73,9 @@ class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeSecureStorageInterface_5 extends _i1.SmartFake
class _FakeSecureStorageInterface_4 extends _i1.SmartFake
implements _i6.SecureStorageInterface {
_FakeSecureStorageInterface_5(
_FakeSecureStorageInterface_4(
Object parent,
Invocation parentInvocation,
) : super(
@ -430,72 +420,24 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i8.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i8.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i8.Future<List<String>>.value(<String>[]),
) as _i8.Future<List<String>>);
@override
_i8.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i8.Future<List<_i13.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i8.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i8.Future<_i4.TransactionData>);
_i8.Future<List<_i13.Transaction>>.value(<_i13.Transaction>[]),
) as _i8.Future<List<_i13.Transaction>>);
@override
_i8.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i8.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i8.Future<List<_i4.UtxoObject>>);
_i8.Future<List<_i13.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i8.Future<List<_i13.UTXO>>.value(<_i13.UTXO>[]),
) as _i8.Future<List<_i13.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -525,6 +467,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -576,24 +523,6 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -683,14 +612,6 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i8.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -742,25 +663,25 @@ class MockManager extends _i1.Mock implements _i12.Manager {
/// A class which mocks [NodeService].
///
/// See the documentation for Mockito's code generation for more information.
class MockNodeService extends _i1.Mock implements _i13.NodeService {
class MockNodeService extends _i1.Mock implements _i14.NodeService {
@override
_i6.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod(
Invocation.getter(#secureStorageInterface),
returnValue: _FakeSecureStorageInterface_5(
returnValue: _FakeSecureStorageInterface_4(
this,
Invocation.getter(#secureStorageInterface),
),
) as _i6.SecureStorageInterface);
@override
List<_i14.NodeModel> get primaryNodes => (super.noSuchMethod(
List<_i15.NodeModel> get primaryNodes => (super.noSuchMethod(
Invocation.getter(#primaryNodes),
returnValue: <_i14.NodeModel>[],
) as List<_i14.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
List<_i14.NodeModel> get nodes => (super.noSuchMethod(
List<_i15.NodeModel> get nodes => (super.noSuchMethod(
Invocation.getter(#nodes),
returnValue: <_i14.NodeModel>[],
) as List<_i14.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
@ -778,7 +699,7 @@ class MockNodeService extends _i1.Mock implements _i13.NodeService {
@override
_i8.Future<void> setPrimaryNodeFor({
required _i10.Coin? coin,
required _i14.NodeModel? node,
required _i15.NodeModel? node,
bool? shouldNotifyListeners = false,
}) =>
(super.noSuchMethod(
@ -795,40 +716,40 @@ class MockNodeService extends _i1.Mock implements _i13.NodeService {
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i14.NodeModel? getPrimaryNodeFor({required _i10.Coin? coin}) =>
_i15.NodeModel? getPrimaryNodeFor({required _i10.Coin? coin}) =>
(super.noSuchMethod(Invocation.method(
#getPrimaryNodeFor,
[],
{#coin: coin},
)) as _i14.NodeModel?);
)) as _i15.NodeModel?);
@override
List<_i14.NodeModel> getNodesFor(_i10.Coin? coin) => (super.noSuchMethod(
List<_i15.NodeModel> getNodesFor(_i10.Coin? coin) => (super.noSuchMethod(
Invocation.method(
#getNodesFor,
[coin],
),
returnValue: <_i14.NodeModel>[],
) as List<_i14.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
_i14.NodeModel? getNodeById({required String? id}) =>
_i15.NodeModel? getNodeById({required String? id}) =>
(super.noSuchMethod(Invocation.method(
#getNodeById,
[],
{#id: id},
)) as _i14.NodeModel?);
)) as _i15.NodeModel?);
@override
List<_i14.NodeModel> failoverNodesFor({required _i10.Coin? coin}) =>
List<_i15.NodeModel> failoverNodesFor({required _i10.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#failoverNodesFor,
[],
{#coin: coin},
),
returnValue: <_i14.NodeModel>[],
) as List<_i14.NodeModel>);
returnValue: <_i15.NodeModel>[],
) as List<_i15.NodeModel>);
@override
_i8.Future<void> add(
_i14.NodeModel? node,
_i15.NodeModel? node,
String? password,
bool? shouldNotifyListeners,
) =>
@ -880,7 +801,7 @@ class MockNodeService extends _i1.Mock implements _i13.NodeService {
) as _i8.Future<void>);
@override
_i8.Future<void> edit(
_i14.NodeModel? editedNode,
_i15.NodeModel? editedNode,
String? password,
bool? shouldNotifyListeners,
) =>

View file

@ -4,10 +4,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i8;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i5;
@ -45,19 +46,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -151,72 +141,24 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i7.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i8.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i3.TransactionData>);
_i7.Future<List<_i8.Transaction>>.value(<_i8.Transaction>[]),
) as _i7.Future<List<_i8.Transaction>>);
@override
_i7.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i7.Future<List<_i3.UtxoObject>>);
_i7.Future<List<_i8.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i8.UTXO>>.value(<_i8.UTXO>[]),
) as _i7.Future<List<_i8.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -246,6 +188,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -297,24 +244,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -404,14 +333,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -435,7 +356,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -443,7 +364,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -4,10 +4,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i8;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i5;
@ -45,19 +46,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -151,72 +141,24 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i7.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i8.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i3.TransactionData>);
_i7.Future<List<_i8.Transaction>>.value(<_i8.Transaction>[]),
) as _i7.Future<List<_i8.Transaction>>);
@override
_i7.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i7.Future<List<_i3.UtxoObject>>);
_i7.Future<List<_i8.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i8.UTXO>>.value(<_i8.UTXO>[]),
) as _i7.Future<List<_i8.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -246,6 +188,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -297,24 +244,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -404,14 +333,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -435,7 +356,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -443,7 +364,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -6,8 +6,9 @@
import 'dart:async' as _i8;
import 'dart:ui' as _i10;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/models/node_model.dart' as _i7;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
@ -60,19 +61,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -366,72 +356,24 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i8.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i8.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i8.Future<List<String>>.value(<String>[]),
) as _i8.Future<List<String>>);
@override
_i8.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i8.Future<List<_i12.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i8.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i8.Future<_i4.TransactionData>);
_i8.Future<List<_i12.Transaction>>.value(<_i12.Transaction>[]),
) as _i8.Future<List<_i12.Transaction>>);
@override
_i8.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i8.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i8.Future<List<_i4.UtxoObject>>);
_i8.Future<List<_i12.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i8.Future<List<_i12.UTXO>>.value(<_i12.UTXO>[]),
) as _i8.Future<List<_i12.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -461,6 +403,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -512,24 +459,6 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -619,14 +548,6 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i8.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -6,8 +6,9 @@
import 'dart:async' as _i8;
import 'dart:ui' as _i10;
import 'package:decimal/decimal.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/models/node_model.dart' as _i7;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
@ -60,19 +61,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -366,72 +356,24 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i8.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i8.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i8.Future<List<String>>.value(<String>[]),
) as _i8.Future<List<String>>);
@override
_i8.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i8.Future<List<_i12.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i8.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i8.Future<_i4.TransactionData>);
_i8.Future<List<_i12.Transaction>>.value(<_i12.Transaction>[]),
) as _i8.Future<List<_i12.Transaction>>);
@override
_i8.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i8.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i8.Future<List<_i4.UtxoObject>>);
_i8.Future<List<_i12.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i8.Future<List<_i12.UTXO>>.value(<_i12.UTXO>[]),
) as _i8.Future<List<_i12.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -461,6 +403,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -512,24 +459,6 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -619,14 +548,6 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i8.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -4,10 +4,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i8;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i5;
@ -45,19 +46,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -151,72 +141,24 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i7.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i8.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i3.TransactionData>);
_i7.Future<List<_i8.Transaction>>.value(<_i8.Transaction>[]),
) as _i7.Future<List<_i8.Transaction>>);
@override
_i7.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i7.Future<List<_i3.UtxoObject>>);
_i7.Future<List<_i8.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i8.UTXO>>.value(<_i8.UTXO>[]),
) as _i7.Future<List<_i8.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -246,6 +188,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -297,24 +244,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -404,14 +333,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -435,7 +356,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -443,7 +364,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -4,10 +4,11 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i7;
import 'dart:ui' as _i8;
import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i8;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i5;
@ -45,19 +46,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -151,72 +141,24 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i7.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i7.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i7.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i7.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i7.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i7.Future<List<String>>.value(<String>[]),
) as _i7.Future<List<String>>);
@override
_i7.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i7.Future<List<_i8.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i7.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i7.Future<_i3.TransactionData>);
_i7.Future<List<_i8.Transaction>>.value(<_i8.Transaction>[]),
) as _i7.Future<List<_i8.Transaction>>);
@override
_i7.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i7.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i7.Future<List<_i3.UtxoObject>>);
_i7.Future<List<_i8.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i7.Future<List<_i8.UTXO>>.value(<_i8.UTXO>[]),
) as _i7.Future<List<_i8.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -246,6 +188,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -297,24 +244,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i7.Future<String>.value(''),
) as _i7.Future<String>);
@override
_i7.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -404,14 +333,6 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);
@override
_i7.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
@ -435,7 +356,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -443,7 +364,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValueForMissingStub: null,
);
@override
void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View file

@ -6,8 +6,9 @@
import 'dart:async' as _i6;
import 'dart:ui' as _i8;
import 'package:decimal/decimal.dart' as _i4;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i4;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i10;
import 'package:stackwallet/models/models.dart' as _i3;
import 'package:stackwallet/services/coins/coin_service.dart' as _i2;
import 'package:stackwallet/services/coins/manager.dart' as _i9;
@ -46,19 +47,8 @@ class _FakeFeeObject_1 extends _i1.SmartFake implements _i3.FeeObject {
);
}
class _FakeDecimal_2 extends _i1.SmartFake implements _i4.Decimal {
_FakeDecimal_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_3 extends _i1.SmartFake
implements _i3.TransactionData {
_FakeTransactionData_3(
class _FakeBalance_2 extends _i1.SmartFake implements _i4.Balance {
_FakeBalance_2(
Object parent,
Invocation parentInvocation,
) : super(
@ -374,72 +364,24 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<_i4.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
_i4.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_2(
this,
Invocation.getter(#availableBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i4.Decimal);
) as _i4.Balance);
@override
_i6.Future<_i4.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#pendingBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i6.Future<_i4.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i6.Future<_i4.Decimal>.value(_FakeDecimal_2(
this,
Invocation.getter(#totalBalance),
)),
) as _i6.Future<_i4.Decimal>);
@override
_i4.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_2(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i4.Decimal);
@override
_i6.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i6.Future<List<String>>.value(<String>[]),
) as _i6.Future<List<String>>);
@override
_i6.Future<_i3.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i6.Future<List<_i10.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i6.Future<_i3.TransactionData>.value(_FakeTransactionData_3(
this,
Invocation.getter(#transactionData),
)),
) as _i6.Future<_i3.TransactionData>);
_i6.Future<List<_i10.Transaction>>.value(<_i10.Transaction>[]),
) as _i6.Future<List<_i10.Transaction>>);
@override
_i6.Future<List<_i3.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i6.Future<List<_i3.UtxoObject>>.value(<_i3.UtxoObject>[]),
) as _i6.Future<List<_i3.UtxoObject>>);
_i6.Future<List<_i10.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i6.Future<List<_i10.UTXO>>.value(<_i10.UTXO>[]),
) as _i6.Future<List<_i10.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -469,6 +411,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -520,24 +467,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i6.Future<String>.value(''),
) as _i6.Future<String>);
@override
_i6.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -627,14 +556,6 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i6.Future<bool>.value(false),
) as _i6.Future<bool>);
@override
_i6.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

View file

@ -6,12 +6,13 @@
import 'dart:async' as _i8;
import 'dart:ui' as _i14;
import 'package:decimal/decimal.dart' as _i5;
import 'package:local_auth/auth_strings.dart' as _i11;
import 'package:local_auth/local_auth.dart' as _i10;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i6;
import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i7;
import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i16;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/coins/coin_service.dart' as _i3;
import 'package:stackwallet/services/coins/manager.dart' as _i15;
@ -62,19 +63,8 @@ class _FakeFeeObject_2 extends _i1.SmartFake implements _i4.FeeObject {
);
}
class _FakeDecimal_3 extends _i1.SmartFake implements _i5.Decimal {
_FakeDecimal_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeTransactionData_4 extends _i1.SmartFake
implements _i4.TransactionData {
_FakeTransactionData_4(
class _FakeBalance_3 extends _i1.SmartFake implements _i5.Balance {
_FakeBalance_3(
Object parent,
Invocation parentInvocation,
) : super(
@ -631,72 +621,24 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<_i5.Decimal> get availableBalance => (super.noSuchMethod(
Invocation.getter(#availableBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
_i5.Balance get balance => (super.noSuchMethod(
Invocation.getter(#balance),
returnValue: _FakeBalance_3(
this,
Invocation.getter(#availableBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedAvailableBalance => (super.noSuchMethod(
Invocation.getter(#cachedAvailableBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedAvailableBalance),
Invocation.getter(#balance),
),
) as _i5.Decimal);
) as _i5.Balance);
@override
_i8.Future<_i5.Decimal> get pendingBalance => (super.noSuchMethod(
Invocation.getter(#pendingBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#pendingBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get balanceMinusMaxFee => (super.noSuchMethod(
Invocation.getter(#balanceMinusMaxFee),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#balanceMinusMaxFee),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i8.Future<_i5.Decimal> get totalBalance => (super.noSuchMethod(
Invocation.getter(#totalBalance),
returnValue: _i8.Future<_i5.Decimal>.value(_FakeDecimal_3(
this,
Invocation.getter(#totalBalance),
)),
) as _i8.Future<_i5.Decimal>);
@override
_i5.Decimal get cachedTotalBalance => (super.noSuchMethod(
Invocation.getter(#cachedTotalBalance),
returnValue: _FakeDecimal_3(
this,
Invocation.getter(#cachedTotalBalance),
),
) as _i5.Decimal);
@override
_i8.Future<List<String>> get allOwnAddresses => (super.noSuchMethod(
Invocation.getter(#allOwnAddresses),
returnValue: _i8.Future<List<String>>.value(<String>[]),
) as _i8.Future<List<String>>);
@override
_i8.Future<_i4.TransactionData> get transactionData => (super.noSuchMethod(
Invocation.getter(#transactionData),
_i8.Future<List<_i16.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i8.Future<_i4.TransactionData>.value(_FakeTransactionData_4(
this,
Invocation.getter(#transactionData),
)),
) as _i8.Future<_i4.TransactionData>);
_i8.Future<List<_i16.Transaction>>.value(<_i16.Transaction>[]),
) as _i8.Future<List<_i16.Transaction>>);
@override
_i8.Future<List<_i4.UtxoObject>> get unspentOutputs => (super.noSuchMethod(
Invocation.getter(#unspentOutputs),
returnValue: _i8.Future<List<_i4.UtxoObject>>.value(<_i4.UtxoObject>[]),
) as _i8.Future<List<_i4.UtxoObject>>);
_i8.Future<List<_i16.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i8.Future<List<_i16.UTXO>>.value(<_i16.UTXO>[]),
) as _i8.Future<List<_i16.UTXO>>);
@override
set walletName(String? newName) => super.noSuchMethod(
Invocation.setter(
@ -726,6 +668,11 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: false,
) as bool);
@override
int get currentHeight => (super.noSuchMethod(
Invocation.getter(#currentHeight),
returnValue: 0,
) as int);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@ -777,24 +724,6 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<String> send({
required String? toAddress,
required int? amount,
Map<String, String>? args = const {},
}) =>
(super.noSuchMethod(
Invocation.method(
#send,
[],
{
#toAddress: toAddress,
#amount: amount,
#args: args,
},
),
returnValue: _i8.Future<String>.value(''),
) as _i8.Future<String>);
@override
_i8.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
@ -884,14 +813,6 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValueForMissingStub: _i8.Future<void>.value(),
) as _i8.Future<void>);
@override
_i8.Future<bool> isOwnAddress(String? address) => (super.noSuchMethod(
Invocation.method(
#isOwnAddress,
[address],
),
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,

Some files were not shown because too many files have changed in this diff Show more