Merge remote-tracking branch 'origin/staging' into tor

This commit is contained in:
Josh Babb 2023-05-17 15:28:59 -05:00
commit 174e9b29a6
80 changed files with 3675 additions and 1217 deletions

Binary file not shown.

Binary file not shown.

View file

@ -41,7 +41,6 @@ class DB {
String boxNameUsedSerialsCache({required Coin coin}) =>
"${coin.name}_usedSerialsCache";
Box<dynamic>? _boxAddressBook;
Box<String>? _boxDebugInfo;
Box<NodeModel>? _boxNodeModels;
Box<NodeModel>? _boxPrimaryNodes;
@ -100,7 +99,6 @@ class DB {
_boxPrefs = await Hive.openBox<dynamic>(boxNamePrefs);
}
_boxAddressBook = await Hive.openBox<dynamic>(boxNameAddressBook);
_boxDebugInfo = await Hive.openBox<String>(boxNameDebugInfo);
if (Hive.isBoxOpen(boxNameNodeModels)) {

View file

@ -3,6 +3,7 @@ import 'package:flutter_native_splash/cli_commands.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/exceptions/main_db/main_db_exception.dart';
import 'package:stackwallet/models/isar/models/block_explorer.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
@ -37,6 +38,7 @@ class MainDB {
EthContractSchema,
TransactionBlockExplorerSchema,
StackThemeSchema,
ContactEntrySchema,
],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
// inspector: kDebugMode,
@ -47,6 +49,45 @@ class MainDB {
return true;
}
// contact entries
List<ContactEntry> getContactEntries(){
return isar.contactEntrys.where().findAllSync();
}
Future<bool> deleteContactEntry({required String id}) {
try {
return isar.writeTxn(() async {
await isar.contactEntrys.deleteByCustomId(id);
return true;
});
} catch (e) {
throw MainDBException("failed deleteContactEntry: $id", e);
}
}
Future<bool> isContactEntryExists({required String id}) async {
return isar.contactEntrys
.where()
.customIdEqualTo(id)
.count()
.then((value) => value > 0);
}
ContactEntry? getContactEntry({required String id}) {
return isar.contactEntrys.where().customIdEqualTo(id).findFirstSync();
}
Future<bool> putContactEntry({required ContactEntry contactEntry}) async {
try {
return await isar.writeTxn(() async {
await isar.contactEntrys.put(contactEntry);
return true;
});
} catch (e) {
throw MainDBException("failed putContactEntry: $contactEntry", e);
}
}
// tx block explorers
TransactionBlockExplorer? getTransactionBlockExplorer({required Coin coin}) {
return isar.transactionBlockExplorers

View file

@ -162,7 +162,7 @@ void main() async {
int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
0;
if (dbVersion < Constants.currentHiveDbVersion) {
if (dbVersion < Constants.currentDataVersion) {
try {
await DbVersionMigrator().migrate(
dbVersion,
@ -178,9 +178,6 @@ void main() async {
}
}
//Add Themes directory - TODO
// await StackFileSystem.applicationThemesDirectory();
monero.onStartup();
wownero.onStartup();

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:uuid/uuid.dart';
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
class Contact {
final String? emojiChar;
final String name;

View file

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
class ContactAddressEntry {
final Coin coin;
final String address;

View file

@ -1,5 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -67,8 +67,11 @@ class AddressEntryData extends ChangeNotifier {
}
ContactAddressEntry buildAddressEntry() {
return ContactAddressEntry(
coin: coin!, address: address!, label: addressLabel!);
return ContactAddressEntry()
..coinName = coin!.name
..address = address!
..other = null
..label = addressLabel!;
}
@override

View file

@ -0,0 +1,108 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
part 'contact_entry.g.dart';
@collection
class ContactEntry {
ContactEntry({
this.emojiChar,
required this.name,
required this.addresses,
required this.isFavorite,
required this.customId,
});
Id id = Isar.autoIncrement;
late final String? emojiChar;
late final String name;
late final List<ContactAddressEntry> addresses;
late final bool isFavorite;
@Index(unique: true, replace: true)
late final String customId;
ContactEntry copyWith({
bool shouldCopyEmojiWithNull = false,
String? emojiChar,
String? name,
List<ContactAddressEntry>? addresses,
bool? isFavorite,
}) {
List<ContactAddressEntry> _addresses = [];
if (addresses == null) {
for (var e in this.addresses) {
_addresses.add(e.copyWith());
}
} else {
for (var e in addresses) {
_addresses.add(e.copyWith());
}
}
String? newEmoji;
if (shouldCopyEmojiWithNull) {
newEmoji = emojiChar;
} else {
newEmoji = emojiChar ?? this.emojiChar;
}
return ContactEntry(
emojiChar: newEmoji,
name: name ?? this.name,
addresses: _addresses,
isFavorite: isFavorite ?? this.isFavorite,
customId: customId,
);
}
Map<String, dynamic> toMap() {
return {
"emoji": emojiChar,
"name": name,
"addresses": addresses.map((e) => e.toMap()).toList(),
"id": customId,
"isFavorite": isFavorite,
};
}
}
@embedded
class ContactAddressEntry {
late final String coinName;
late final String address;
late final String label;
late final String? other;
@ignore
Coin get coin => Coin.values.byName(coinName);
ContactAddressEntry();
ContactAddressEntry copyWith({
Coin? coin,
String? address,
String? label,
String? other,
}) {
return ContactAddressEntry()
..coinName = coin?.name ?? coinName
..address = address ?? this.address
..label = label ?? this.label
..other = other ?? this.other;
}
Map<String, String> toMap() {
return {
"label": label,
"address": address,
"coin": coin.name,
"other": other ?? "",
};
}
@override
String toString() {
return "AddressBookEntry: ${toMap()}";
}
}

File diff suppressed because it is too large Load diff

View file

@ -794,6 +794,15 @@ class StackTheme {
Color? _bottomNavIconIcon;
final int bottomNavIconIconInt;
// ==== bottomNavIconIcon highlighted =====================================================
@ignore
Color get bottomNavIconIconHighlighted =>
_bottomNavIconIconHighlighted ??= Color(bottomNavIconIconHighlightedInt);
@ignore
Color? _bottomNavIconIconHighlighted;
final int bottomNavIconIconHighlightedInt;
// ==== topNavIconPrimary =====================================================
@ignore
@ -1556,6 +1565,7 @@ class StackTheme {
required this.snackBarTextInfoInt,
required this.bottomNavIconBackInt,
required this.bottomNavIconIconInt,
required this.bottomNavIconIconHighlightedInt,
required this.topNavIconPrimaryInt,
required this.topNavIconGreenInt,
required this.topNavIconYellowInt,
@ -1795,6 +1805,8 @@ class StackTheme {
parseColor(json["colors"]["bottom_nav_icon_back"] as String),
bottomNavIconIconInt:
parseColor(json["colors"]["bottom_nav_icon_icon"] as String),
bottomNavIconIconHighlightedInt: parseColor(
json["colors"]["bottom_nav_icon_icon_highlighted"] as String),
topNavIconPrimaryInt:
parseColor(json["colors"]["top_nav_icon_primary"] as String),
topNavIconGreenInt:

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,14 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/models/notification_model.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
@ -9,7 +16,7 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class NotificationCard extends StatelessWidget {
class NotificationCard extends ConsumerWidget {
const NotificationCard({
Key? key,
required this.notification,
@ -25,8 +32,17 @@ class NotificationCard extends StatelessWidget {
static const double mobileIconSize = 24;
static const double desktopIconSize = 30;
String coinIconPath(ThemeAssets assets, WidgetRef ref) {
try {
final coin = coinFromPrettyName(notification.coinName);
return ref.read(coinIconProvider(coin));
} catch (_) {
return notification.iconAssetName;
}
}
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
final isDesktop = Util.isDesktop;
return Stack(
@ -41,8 +57,14 @@ class NotificationCard extends StatelessWidget {
child: Row(
children: [
notification.changeNowId == null
? SvgPicture.asset(
notification.iconAssetName,
? SvgPicture.file(
File(
coinIconPath(
ref.watch(
themeProvider.select((value) => value.assets),
),
ref),
),
width: isDesktop ? desktopIconSize : mobileIconSize,
height: isDesktop ? desktopIconSize : mobileIconSize,
)
@ -53,8 +75,14 @@ class NotificationCard extends StatelessWidget {
color: Colors.transparent,
borderRadius: BorderRadius.circular(24),
),
child: SvgPicture.asset(
notification.iconAssetName,
child: SvgPicture.file(
File(
coinIconPath(
ref.watch(
themeProvider.select((value) => value.assets),
),
ref),
),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,

View file

@ -1,8 +1,7 @@
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/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
@ -73,19 +72,18 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
final managers = ref.read(walletsChangeNotifierProvider).managers;
for (final manager in managers) {
addresses.add(
ContactAddressEntry(
coin: manager.coin,
address: await manager.currentReceivingAddress,
label: "Current Receiving",
other: manager.walletName,
),
ContactAddressEntry()
..coinName = manager.coin.name
..address = await manager.currentReceivingAddress
..label = "Current Receiving"
..other = manager.walletName,
);
}
final self = Contact(
final self = ContactEntry(
name: "My Stack",
addresses: addresses,
isFavorite: true,
id: "default",
customId: "default",
);
await ref.read(addressBookServiceProvider).editContact(self);
});
@ -306,8 +304,8 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
.where((element) => element.isFavorite)
.map(
(e) => AddressBookCard(
key: Key("favContactCard_${e.id}_key"),
contactId: e.id,
key: Key("favContactCard_${e.customId}_key"),
contactId: e.customId,
),
),
],
@ -352,8 +350,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
.matches(widget.filterTerm ?? _searchTerm, e))
.map(
(e) => AddressBookCard(
key: Key("desktopContactCard_${e.id}_key"),
contactId: e.id,
key:
Key("desktopContactCard_${e.customId}_key"),
contactId: e.customId,
),
),
],

View file

@ -2,8 +2,7 @@ import 'package:emojis/emoji.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@ -28,6 +27,7 @@ import 'package:stackwallet/widgets/emoji_select_sheet.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'package:uuid/uuid.dart';
class AddAddressBookEntryView extends ConsumerStatefulWidget {
const AddAddressBookEntryView({
@ -688,11 +688,12 @@ class _AddAddressBookEntryViewState
forms[i].id))
.buildAddressEntry());
}
Contact contact = Contact(
ContactEntry contact = ContactEntry(
emojiChar: _selectedEmoji?.char,
name: nameController.text,
addresses: entries,
isFavorite: _isFavorite,
customId: const Uuid().v1(),
);
if (await ref

View file

@ -1,8 +1,7 @@
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/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@ -208,7 +207,7 @@ class _AddNewContactAddressViewState
.read(addressEntryDataProvider(0))
.buildAddressEntry());
Contact editedContact =
ContactEntry editedContact =
contact.copyWith(addresses: entries);
if (await ref

View file

@ -1,9 +1,11 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_image_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -87,8 +89,10 @@ class CoinSelectSheet extends StatelessWidget {
padding: const EdgeInsets.all(12),
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinImageProvider(coin)),
),
height: 20,
width: 20,
),

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@ -13,8 +15,8 @@ import 'package:stackwallet/providers/global/address_book_service_provider.dart'
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -197,7 +199,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
onPressed: () {
ref
.read(addressBookServiceProvider)
.removeContact(_contact.id);
.removeContact(_contact.customId);
Navigator.of(context).pop();
Navigator.of(context).pop();
showFloatingFlushBar(
@ -334,8 +336,10 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
padding: const EdgeInsets.all(12),
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(e.coin)),
),
height: 24,
),
const SizedBox(

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@ -9,8 +11,8 @@ import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.
import 'package:stackwallet/pages/send_view/send_view.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
@ -110,11 +112,13 @@ class ContactPopUp extends ConsumerWidget {
),
child: contact.id == "default"
? Center(
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) =>
value.assets.stackIcon,
(value) => value
.assets.stackIcon,
),
),
),
width: 20,
@ -211,10 +215,12 @@ class ContactPopUp extends ConsumerWidget {
const SizedBox(
height: 2,
),
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(
coinIconProvider(e.coin),
),
),
height: 24,
),
],

View file

@ -1,8 +1,7 @@
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/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@ -49,7 +48,7 @@ class _EditContactAddressViewState
late final BarcodeScannerInterface barcodeScanner;
late final ClipboardInterface clipboard;
Future<void> save(Contact contact) async {
Future<void> save(ContactEntry contact) async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
@ -73,7 +72,7 @@ class _EditContactAddressViewState
entries.insert(index, editedEntry);
Contact editedContact = contact.copyWith(addresses: entries);
ContactEntry editedContact = contact.copyWith(addresses: entries);
if (await ref.read(addressBookServiceProvider).editContact(editedContact)) {
if (mounted) {
@ -226,7 +225,8 @@ class _EditContactAddressViewState
);
_addresses.remove(entry);
Contact editedContact = contact.copyWith(addresses: _addresses);
ContactEntry editedContact =
contact.copyWith(addresses: _addresses);
if (await ref
.read(addressBookServiceProvider)
.editContact(editedContact)) {

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -7,8 +9,8 @@ import 'package:stackwallet/pages/address_book_views/subviews/coin_select_sheet.
import 'package:stackwallet/providers/providers.dart';
// import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
@ -141,8 +143,10 @@ class _NewContactAddressEntryFormState
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
height: 24,
width: 24,
),
@ -211,7 +215,8 @@ class _NewContactAddressEntryFormState
)
: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(
coinIconProvider(
ref.watch(
@ -222,6 +227,7 @@ class _NewContactAddressEntryFormState
)!,
),
),
),
height: 20,
width: 20,
),

View file

@ -144,7 +144,7 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
aspectRatio: 1,
child: AppBarIconButton(
semanticsLabel:
"Address List Pop-up Button. Opens A Pop-up For Adress List Button.",
"Address List Pop-up Button. Opens A Pop-up For Address List Button.",
key: const Key("walletNetworkSettingsAddNewNodeViewButton"),
size: 36,
shadows: const [],

View file

@ -35,6 +35,12 @@ class _ManageExplorerViewState extends ConsumerState<ManageExplorerView> {
.replaceAll("%5BTXID%5D", "[TXID]"));
}
@override
void dispose() {
textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Background(
@ -93,13 +99,19 @@ class _ManageExplorerViewState extends ConsumerState<ManageExplorerView> {
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonStyle(context),
onPressed: () {
onPressed: () async {
textEditingController.text =
textEditingController.text.trim();
setBlockExplorerForCoin(
await setBlockExplorerForCoin(
coin: widget.coin,
url: Uri.parse(textEditingController.text))
.then((value) => Navigator.of(context).pop());
url: Uri.parse(
textEditingController.text,
),
);
if (mounted) {
Navigator.of(context).pop();
}
},
child: Text(
"Save",

View file

@ -191,7 +191,8 @@ class GlobalSettingsView extends StatelessWidget {
title: "Appearance",
onPressed: () {
Navigator.of(context).pushNamed(
AppearanceSettingsView.routeName);
AppearanceSettingsView.routeName,
);
},
),
if (Platform.isIOS)

View file

@ -5,10 +5,9 @@ import 'dart:typed_data';
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/stack_restoring_ui_state.dart';
import 'package:stackwallet/models/trade_wallet_lookup.dart';
@ -266,7 +265,7 @@ abstract class SWB {
);
AddressBookService addressBookService = AddressBookService();
var addresses = await addressBookService.addressBookEntries;
var addresses = addressBookService.contacts;
backupJson['addressBookEntries'] =
addresses.map((e) => e.toMap()).toList();
@ -799,7 +798,7 @@ abstract class SWB {
// contacts
final addressBookService = AddressBookService();
final allContactIds = addressBookService.contacts.map((e) => e.id);
final allContactIds = addressBookService.contacts.map((e) => e.customId);
if (addressBookEntries == null) {
// if no contacts were present before attempted restore then delete any that
@ -823,21 +822,20 @@ abstract class SWB {
List<ContactAddressEntry> addresses = [];
for (var address in (contact['addresses'] as List<dynamic>)) {
addresses.add(
ContactAddressEntry(
coin: Coin.values
.firstWhere((element) => element.name == address['coin']),
address: address['address'] as String,
label: address['label'] as String,
),
ContactAddressEntry()
..coinName = address['coin'] as String
..address = address['address'] as String
..label = address['label'] as String
..other = address['other'] as String?,
);
}
await addressBookService.editContact(
Contact(
ContactEntry(
emojiChar: contact['emoji'] as String?,
name: contact['name'] as String,
addresses: addresses,
isFavorite: contact['isFavorite'] as bool,
id: contact['id'] as String,
customId: contact['id'] as String,
),
);
} else {
@ -1026,21 +1024,20 @@ abstract class SWB {
List<ContactAddressEntry> addresses = [];
for (var address in (contact['addresses'] as List<dynamic>)) {
addresses.add(
ContactAddressEntry(
coin: Coin.values
.firstWhere((element) => element.name == address['coin']),
address: address['address'] as String,
label: address['label'] as String,
),
ContactAddressEntry()
..coinName = address['coin'] as String
..address = address['address'] as String
..label = address['label'] as String
..other = address['other'] as String?,
);
}
await addressBookService.addContact(
Contact(
ContactEntry(
emojiChar: contact['emoji'] as String?,
name: contact['name'] as String,
addresses: addresses,
isFavorite: contact['isFavorite'] as bool,
id: contact['id'] as String,
customId: contact['id'] as String,
),
);
}

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -6,8 +8,8 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_widgets/restoring_item_card.dart';
import 'package:stackwallet/providers/stack_restore/stack_restoring_ui_state_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
@ -81,8 +83,10 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
.extension<StackColors>()!
.colorForCoin(coin),
child: Center(
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
height: 20,
width: 20,
),
@ -222,10 +226,12 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
.extension<StackColors>()!
.colorForCoin(coin),
child: Center(
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
coinIconProvider(coin),
),
),
height: 20,
width: 20,
),

View file

@ -1,10 +1,12 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/background.dart';
@ -236,7 +238,8 @@ class _StartupPreferencesViewState
.only(top: 12),
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(
coinIconProvider(
ref
@ -255,6 +258,7 @@ class _StartupPreferencesViewState
),
),
),
),
const SizedBox(
width: 10,
),

View file

@ -1,9 +1,11 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/background.dart';
@ -102,10 +104,12 @@ class _StartupWalletSelectionViewState
),
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
coinIconProvider(manager.coin),
),
),
width: 20,
height: 20,
),

View file

@ -1,9 +1,11 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
@ -116,10 +118,12 @@ class WalletSyncingOptionsView extends ConsumerWidget {
),
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
coinIconProvider(manager.coin),
),
),
width: 20,
height: 20,
),

View file

@ -8,7 +8,6 @@ import 'package:qr_flutter/qr_flutter.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/mixins/xpubable.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
@ -177,7 +176,7 @@ class _XPubViewState extends ConsumerState<XPubView> {
child: child,
),
child: FutureBuilder(
future: (manager.wallet as XPubAble).xpub,
future: manager.xpub,
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {

View file

@ -33,7 +33,7 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:tuple/tuple.dart';
/// [eventBus] should only be set during testing
class WalletSettingsView extends StatefulWidget {
class WalletSettingsView extends ConsumerStatefulWidget {
const WalletSettingsView({
Key? key,
required this.walletId,
@ -52,10 +52,10 @@ class WalletSettingsView extends StatefulWidget {
final EventBus? eventBus;
@override
State<WalletSettingsView> createState() => _WalletSettingsViewState();
ConsumerState<WalletSettingsView> createState() => _WalletSettingsViewState();
}
class _WalletSettingsViewState extends State<WalletSettingsView> {
class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
late final String walletId;
late final Coin coin;
late String xpub;
@ -74,7 +74,7 @@ class _WalletSettingsViewState extends State<WalletSettingsView> {
walletId = widget.walletId;
coin = widget.coin;
xPubEnabled =
coin != Coin.monero && coin != Coin.wownero && coin != Coin.epicCash;
ref.read(walletsChangeNotifierProvider).getManager(walletId).hasXPub;
xpub = "";
_currentSyncStatus = widget.initialSyncStatus;

View file

@ -308,7 +308,16 @@ class TokenOptionsButton extends StatelessWidget {
child: child,
),
),
child: SvgPicture.file(
child: iconAssetPathSVG.startsWith("assets/")
? SvgPicture.asset(
iconAssetPathSVG,
color: Theme.of(context)
.extension<StackColors>()!
.tokenSummaryIcon,
width: iconSize,
height: iconSize,
)
: SvgPicture.file(
File(iconAssetPathSVG),
color: Theme.of(context)
.extension<StackColors>()!

View file

@ -23,19 +23,6 @@ class TxIcon extends ConsumerWidget {
static const Size size = Size(32, 32);
// String _getBundleAssetName(
// bool isCancelled, bool isReceived, bool isPending, BuildContext context) {
// if (!isReceived && transaction.subType == TransactionSubType.mint) {
// if (isCancelled) {
// return Assets.svg.anonymizeFailed;
// }
// if (isPending) {
// return Assets.svg.anonymizePending;
// }
// return Assets.svg.anonymize;
// }
// }
String _getAssetName(
bool isCancelled, bool isReceived, bool isPending, ThemeAssets assets) {
if (!isReceived && transaction.subType == TransactionSubType.mint) {

View file

@ -3,8 +3,8 @@ import 'dart:async';
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/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/isar/models/contact_entry.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';
@ -120,8 +120,8 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
}).toList();
}
bool _isKeywordMatch(Transaction tx, String keyword, List<Contact> contacts,
Map<String, String> notes) {
bool _isKeywordMatch(Transaction tx, String keyword,
List<ContactEntry> contacts, Map<String, String> notes) {
if (keyword.isEmpty) {
return true;
}

View file

@ -1,8 +1,7 @@
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/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_book_scaffold.dart';
@ -105,19 +104,18 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
final managers = ref.read(walletsChangeNotifierProvider).managers;
for (final manager in managers) {
addresses.add(
ContactAddressEntry(
coin: manager.coin,
address: await manager.currentReceivingAddress,
label: "Current Receiving",
other: manager.walletName,
),
ContactAddressEntry()
..coinName = manager.coin.name
..address = await manager.currentReceivingAddress
..label = "Current Receiving"
..other = manager.walletName,
);
}
final self = Contact(
final self = ContactEntry(
name: "My Stack",
addresses: addresses,
isFavorite: true,
id: "default",
customId: "default",
);
await ref.read(addressBookServiceProvider).editContact(self);
});
@ -323,14 +321,14 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
.extension<StackColors>()!
.accentColorDark
.withOpacity(
currentContactId == favorites[i].id
currentContactId == favorites[i].customId
? 0.08
: 0,
),
child: RawMaterialButton(
onPressed: () {
setState(() {
currentContactId = favorites[i].id;
currentContactId = favorites[i].customId;
});
},
padding: const EdgeInsets.symmetric(
@ -346,8 +344,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
),
child: AddressBookCard(
key: Key(
"favContactCard_${favorites[i].id}_key"),
contactId: favorites[i].id,
"favContactCard_${favorites[i].customId}_key"),
contactId: favorites[i].customId,
desktopSendFrom: false,
),
),
@ -393,14 +391,16 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
.extension<StackColors>()!
.accentColorDark
.withOpacity(
currentContactId == allContacts[i].id
currentContactId ==
allContacts[i].customId
? 0.08
: 0,
),
child: RawMaterialButton(
onPressed: () {
setState(() {
currentContactId = allContacts[i].id;
currentContactId =
allContacts[i].customId;
});
},
padding: const EdgeInsets.symmetric(
@ -416,8 +416,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
),
child: AddressBookCard(
key: Key(
"favContactCard_${allContacts[i].id}_key"),
contactId: allContacts[i].id,
"favContactCard_${allContacts[i].customId}_key"),
contactId: allContacts[i].customId,
desktopSendFrom: false,
),
),

View file

@ -2,12 +2,12 @@ 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/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';

View file

@ -1,8 +1,11 @@
import 'dart:io';
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/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/models/contact_entry.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';
@ -24,8 +27,6 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/transaction_card.dart';
import 'package:tuple/tuple.dart';
import '../../../db/isar/main_db.dart';
class DesktopContactDetails extends ConsumerStatefulWidget {
const DesktopContactDetails({
Key? key,
@ -42,7 +43,7 @@ class DesktopContactDetails extends ConsumerStatefulWidget {
class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
List<Tuple2<String, Transaction>> _cachedTransactions = [];
bool _contactHasAddress(String address, Contact contact) {
bool _contactHasAddress(String address, ContactEntry contact) {
for (final entry in contact.addresses) {
if (entry.address == address) {
return true;
@ -82,7 +83,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
@override
Widget build(BuildContext context) {
// provider hack to prevent trying to update widget with deleted contact
Contact? _contact;
ContactEntry? _contact;
try {
_contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(widget.contactId)));
@ -117,14 +118,16 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(32),
),
child: contact.id == "default"
child: contact.customId == "default"
? Center(
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
),
),
),
width: 32,
),
)
@ -159,7 +162,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
barrierColor: Colors.transparent,
builder: (context) {
return DesktopContactOptionsMenuPopup(
contactId: contact.id,
contactId: contact.customId,
);
},
);
@ -261,7 +264,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
padding: const EdgeInsets.all(18),
child: DesktopAddressCard(
entry: contact.addresses[i],
contactId: contact.id,
contactId: contact.customId,
),
),
],

View file

@ -147,7 +147,7 @@ class _DesktopContactOptionsMenuPopupState
onPressed: () {
ref
.read(addressBookServiceProvider)
.removeContact(contact.id);
.removeContact(contact.customId);
Navigator.of(context).pop();
showFloatingFlushBar(
type: FlushBarType.success,

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -6,8 +8,8 @@ import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
@ -359,8 +361,10 @@ class _DesktopCoinControlUseDialogState
color: Colors.transparent,
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
width: 24,
height: 24,
),

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -7,8 +9,8 @@ import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
import 'package:stackwallet/pages_desktop_specific/coin_control/freeze_button.dart';
import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -343,8 +345,10 @@ class _DesktopCoinControlViewState
color: Colors.transparent,
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
width: 24,
height: 24,
),

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
@ -522,10 +523,14 @@ class _DesktopTradeRowCardState extends ConsumerState<DesktopTradeRowCard> {
borderRadius: BorderRadius.circular(32),
),
child: Center(
child: SvgPicture.asset(
child: SvgPicture.file(
File(
_fetchIconAssetForStatus(
trade.status,
ref.watch(themeProvider.select((value) => value.assets)),
ref.watch(
themeProvider.select((value) => value.assets),
),
),
),
width: 32,
height: 32,

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -81,15 +83,21 @@ class DesktopNotificationsIcon extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return SvgPicture.asset(
ref.watch(notificationsProvider
return ref.watch(notificationsProvider
.select((value) => value.hasUnreadNotifications))
? ref.watch(
? SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.bellNew,
),
),
),
width: 20,
height: 20,
)
: Assets.svg.bell,
: SvgPicture.asset(
Assets.svg.bell,
width: 20,
height: 20,
color: ref.watch(notificationsProvider
@ -97,7 +105,9 @@ class DesktopNotificationsIcon extends ConsumerWidget {
? null
: DesktopMenuItemId.notifications ==
ref.watch(currentDesktopMenuItemProvider.state).state
? Theme.of(context).extension<StackColors>()!.accentColorDark
? Theme.of(context)
.extension<StackColors>()!
.accentColorDark
: Theme.of(context)
.extension<StackColors>()!
.accentColorDark

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -53,7 +55,8 @@ class DesktopMyStackTitle extends ConsumerWidget {
SizedBox(
width: 32,
height: 32,
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
@ -61,6 +64,7 @@ class DesktopMyStackTitle extends ConsumerWidget {
),
),
),
),
const SizedBox(
width: 12,
),

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -10,8 +12,8 @@ import 'package:stackwallet/providers/global/price_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
@ -81,8 +83,10 @@ class _DesktopPaynymSendDialogState
// Theme.of(context).extension<StackColors>()!.textSubtitle4,
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
width: 36,
height: 36,
),

View file

@ -1,10 +1,12 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/wallets_view/wallets_overview.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -141,8 +143,10 @@ class _DesktopWalletSummaryRowState
flex: 4,
child: Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(widget.coin)),
),
width: 28,
height: 28,
),

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
@ -34,7 +34,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
String _searchTerm = "";
int _compareContactFavorite(Contact a, Contact b) {
int _compareContactFavorite(ContactEntry a, ContactEntry b) {
if (a.isFavorite && b.isFavorite) {
return 0;
} else if (a.isFavorite) {
@ -44,8 +44,8 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
}
}
List<Contact> pullOutFavorites(List<Contact> contacts) {
final List<Contact> favorites = [];
List<ContactEntry> pullOutFavorites(List<ContactEntry> contacts) {
final List<ContactEntry> favorites = [];
contacts.removeWhere((contact) {
if (contact.isFavorite) {
favorites.add(contact);
@ -57,7 +57,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
return favorites;
}
List<Contact> filter(List<Contact> contacts, String searchTerm) {
List<ContactEntry> filter(List<ContactEntry> contacts, String searchTerm) {
if (widget.coin != null) {
contacts.removeWhere(
(e) => e.addresses.where((a) => a.coin == widget.coin!).isEmpty);
@ -75,7 +75,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
return contacts;
}
bool _matches(String term, Contact contact) {
bool _matches(String term, ContactEntry contact) {
final text = term.toLowerCase();
if (contact.name.toLowerCase().contains(text)) {
return true;
@ -191,7 +191,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
),
child: Consumer(
builder: (context, ref, _) {
List<Contact> contacts = ref
List<ContactEntry> contacts = ref
.watch(addressBookServiceProvider
.select((value) => value.contacts))
.toList();
@ -228,7 +228,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
),
);
} else if (index < favorites.length + 1) {
final id = favorites[index - 1].id;
final id = favorites[index - 1].customId;
return ContactListItem(
key: Key("contactContactListItem_${id}_key"),
contactId: id,
@ -248,7 +248,8 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
),
);
} else {
final id = contacts[index - favorites.length - 2].id;
final id =
contacts[index - favorites.length - 2].customId;
return ContactListItem(
key: Key("contactContactListItem_${id}_key"),
contactId: id,

View file

@ -94,12 +94,14 @@ class _ForgotPasswordDesktopViewState
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
),
),
),
width: 100,
),
const SizedBox(

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@ -54,7 +55,7 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
0;
if (dbVersion < Constants.currentHiveDbVersion) {
if (dbVersion < Constants.currentDataVersion) {
try {
await DbVersionMigrator().migrate(
dbVersion,
@ -166,12 +167,14 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
),
),
),
width: 100,
),
const SizedBox(

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -47,12 +49,14 @@ class _ForgotPasswordDesktopViewState
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
),
),
),
width: 100,
),
const SizedBox(

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/debug_info_dialog.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_manage_block_explorers_dialog.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
@ -58,7 +59,7 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
),
TextSpan(
text:
"\n\nConfigurate these settings only if you know what you are doing!",
"\n\nConfigure these settings only if you know what you are doing!",
style: STextStyles.desktopTextExtraExtraSmall(
context),
),
@ -183,7 +184,7 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
PrimaryButton(
label: "Change",
buttonHeight: ButtonHeight.xs,
width: 86,
width: 101,
onPressed: () async {
await showDialog<dynamic>(
context: context,
@ -207,8 +208,6 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
thickness: 0.5,
),
),
/// TODO: Make a dialog popup
Padding(
padding: const EdgeInsets.all(10),
child: Row(
@ -241,6 +240,44 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
],
),
),
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(
thickness: 0.5,
),
),
Padding(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Block explorers",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark),
textAlign: TextAlign.left,
),
PrimaryButton(
buttonHeight: ButtonHeight.xs,
label: "Edit",
width: 101,
onPressed: () async {
await showDialog<dynamic>(
context: context,
useSafeArea: false,
barrierDismissible: true,
builder: (context) {
return const DesktopManageBlockExplorersDialog();
},
);
},
),
],
),
),
],
),
),

View file

@ -0,0 +1,266 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
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/text_styles.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class DesktopManageBlockExplorersDialog extends ConsumerWidget {
const DesktopManageBlockExplorersDialog({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
bool showTestNet = ref.watch(
prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
);
final List<Coin> coins = showTestNet
? Coin.values
: Coin.values.sublist(0, Coin.values.length - kTestNetCoinCount);
return DesktopDialog(
maxHeight: 850,
maxWidth: 600,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(32),
child: Text(
"Manage block explorers",
style: STextStyles.desktopH3(context),
textAlign: TextAlign.center,
),
),
const DesktopDialogCloseButton(),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: ListView.separated(
itemCount: coins.length,
separatorBuilder: (_, __) => const SizedBox(
height: 12,
),
itemBuilder: (_, index) {
final coin = coins[index];
return RoundedWhiteContainer(
padding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 14,
),
borderColor: Theme.of(context)
.extension<StackColors>()!
.textSubtitle6,
child: Row(
children: [
SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
width: 24,
height: 24,
),
const SizedBox(
width: 12,
),
Expanded(
child: Text(
"${coin.prettyName} block explorer",
style: STextStyles.desktopTextSmall(context),
),
),
const SizedBox(
width: 12,
),
SvgPicture.asset(
Assets.svg.chevronRight,
width: 20,
height: 20,
),
],
),
onPressed: () {
showDialog<dynamic>(
context: context,
useSafeArea: false,
barrierDismissible: true,
builder: (context) {
return _DesktopEditBlockExplorerDialog(
coin: coin,
);
},
);
},
);
},
),
),
),
],
),
);
}
}
class _DesktopEditBlockExplorerDialog extends ConsumerStatefulWidget {
const _DesktopEditBlockExplorerDialog({Key? key, required this.coin})
: super(key: key);
final Coin coin;
@override
ConsumerState<_DesktopEditBlockExplorerDialog> createState() =>
_DesktopEditBlockExplorerDialogState();
}
class _DesktopEditBlockExplorerDialogState
extends ConsumerState<_DesktopEditBlockExplorerDialog> {
late final TextEditingController _textEditingController;
late final FocusNode _focusNode;
@override
void initState() {
_textEditingController = TextEditingController(
text:
getBlockExplorerTransactionUrlFor(coin: widget.coin, txid: "[TXID]")
.toString()
.replaceAll("%5BTXID%5D", "[TXID]"));
_focusNode = FocusNode();
super.initState();
}
@override
void dispose() {
_textEditingController.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DesktopDialog(
maxHeight: double.infinity,
maxWidth: 600,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(32),
child: Text(
"${widget.coin.prettyName} block explorer",
style: STextStyles.desktopH3(context),
textAlign: TextAlign.center,
),
),
const DesktopDialogCloseButton(),
],
),
Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
autocorrect: false,
enableSuggestions: false,
key: const Key("addCustomNodeNodeAddressFieldKey"),
controller: _textEditingController,
focusNode: _focusNode,
style: STextStyles.field(context),
),
),
const SizedBox(
height: 16,
),
RoundedWhiteContainer(
borderColor:
Theme.of(context).extension<StackColors>()!.textSubtitle6,
child: Text(
"Edit your block explorer above. Keep in mind that"
" every block explorer has a slightly different URL scheme."
"\n\n"
"Paste in your block explorer of choice, then edit in"
" [TXID] where the transaction ID should go, and Stack"
" Wallet will auto fill the transaction ID in that place"
" of the URL.",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
),
const SizedBox(
height: 16,
),
Row(
children: [
Expanded(
child: SecondaryButton(
label: "Cancel",
buttonHeight: ButtonHeight.l,
onPressed: Navigator.of(context).pop,
),
),
const SizedBox(
width: 16,
),
Expanded(
child: PrimaryButton(
label: "Save",
buttonHeight: ButtonHeight.l,
onPressed: () async {
_textEditingController.text =
_textEditingController.text.trim();
await setBlockExplorerForCoin(
coin: widget.coin,
url: Uri.parse(
_textEditingController.text,
),
);
if (mounted) {
Navigator.of(context).pop();
}
},
),
),
],
)
],
),
)
],
),
);
}
}

View file

@ -6,8 +6,8 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -250,8 +250,10 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
children: [
Row(
children: [
SvgPicture.asset(
SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
),
width: 24,
height: 24,
),

View file

@ -5,7 +5,6 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
import 'package:stackwallet/models/buy/response_objects/quote.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/isar/models/isar_models.dart';
@ -153,6 +152,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/widgets/choose_coin_view.dart';
import 'package:tuple/tuple.dart';
import 'models/isar/models/contact_entry.dart';
class RouteGenerator {
static const bool useMaterialPageRoute = true;

View file

@ -1,55 +1,33 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
class AddressBookService extends ChangeNotifier {
Contact getContactById(String id) {
final json = DB.instance
.get<dynamic>(boxName: DB.boxNameAddressBook, key: id) as Map?;
if (json == null) {
Logging.instance
.log("Attempted to get non existing contact", level: LogLevel.Fatal);
ContactEntry getContactById(String id) {
ContactEntry? contactEntry = MainDB.instance.getContactEntry(id: id);
if (contactEntry == null) {
throw Exception('Contact ID "$id" not found!');
} else {
return contactEntry;
}
return Contact.fromJson(Map<String, dynamic>.from(json));
}
List<Contact> get contacts {
final keys = List<String>.from(
DB.instance.keys<dynamic>(boxName: DB.boxNameAddressBook));
final _contacts = keys
.map((id) => Contact.fromJson(Map<String, dynamic>.from(DB.instance
.get<dynamic>(boxName: DB.boxNameAddressBook, key: id) as Map)))
.toList(growable: false);
_contacts
.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
return _contacts;
}
Future<List<Contact>>? _addressBookEntries;
Future<List<Contact>> get addressBookEntries =>
_addressBookEntries ??= _fetchAddressBookEntries();
// Load address book contact entries
Future<List<Contact>> _fetchAddressBookEntries() async {
return contacts;
}
List<ContactEntry> get contacts => MainDB.instance.getContactEntries();
/// search address book entries
//TODO optimize address book search?
Future<List<Contact>> search(String text) async {
if (text.isEmpty) return addressBookEntries;
var results = (await addressBookEntries).toList();
//TODO search using isar queries
Future<List<ContactEntry>> search(String text) async {
if (text.isEmpty) return contacts;
var results = contacts.toList();
results.retainWhere((contact) => matches(text, contact));
return results;
}
bool matches(String term, Contact contact) {
bool matches(String term, ContactEntry contact) {
if (term.isEmpty) {
return true;
}
@ -73,44 +51,27 @@ class AddressBookService extends ChangeNotifier {
///
/// returns false if it provided [contact]'s id already exists in the database
/// other true if the [contact] was saved
Future<bool> addContact(Contact contact) async {
if (DB.instance.containsKey<dynamic>(
boxName: DB.boxNameAddressBook, key: contact.id)) {
Future<bool> addContact(ContactEntry contact) async {
if (await MainDB.instance.isContactEntryExists(id: contact.customId)) {
return false;
}
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contact.id,
value: contact.toMap());
Logging.instance.log("add address book entry saved", level: LogLevel.Info);
await _refreshAddressBookEntries();
} else {
await MainDB.instance.putContactEntry(contactEntry: contact);
notifyListeners();
return true;
}
}
/// Edit contact
Future<bool> editContact(Contact editedContact) async {
Future<bool> editContact(ContactEntry editedContact) async {
// over write the contact with edited version
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: editedContact.id,
value: editedContact.toMap());
Logging.instance.log("edit address book entry saved", level: LogLevel.Info);
await _refreshAddressBookEntries();
await MainDB.instance.putContactEntry(contactEntry: editedContact);
notifyListeners();
return true;
}
/// Remove address book contact entry from db if it exists
Future<void> removeContact(String id) async {
await DB.instance.delete<dynamic>(key: id, boxName: DB.boxNameAddressBook);
await _refreshAddressBookEntries();
}
Future<void> _refreshAddressBookEntries() async {
final newAddressBookEntries = await _fetchAddressBookEntries();
_addressBookEntries = Future(() => newAddressBookEntries);
await MainDB.instance.deleteContactEntry(id: id);
notifyListeners();
}
}

View file

@ -53,11 +53,11 @@ import 'package:uuid/uuid.dart';
const int MINIMUM_CONFIRMATIONS = 1;
final Amount DUST_LIMIT = Amount(
rawValue: BigInt.from(294),
fractionDigits: Coin.particl.decimals,
fractionDigits: Coin.bitcoin.decimals,
);
final Amount DUST_LIMIT_P2PKH = Amount(
rawValue: BigInt.from(546),
fractionDigits: Coin.particl.decimals,
fractionDigits: Coin.bitcoin.decimals,
);
const String GENESIS_HASH_MAINNET =

View file

@ -71,7 +71,6 @@ String constructDerivePath({
case 0x80: // bch mainnet wif
switch (derivePathType) {
case DerivePathType.bip44:
case DerivePathType.bip49:
coinType = 145; // bch mainnet
break;
case DerivePathType.bch44: // bitcoin.com wallet specific
@ -95,9 +94,6 @@ String constructDerivePath({
case DerivePathType.bch44:
purpose = 44;
break;
case DerivePathType.bip49:
purpose = 49;
break;
default:
throw Exception("DerivePathType $derivePathType not supported");
}
@ -283,10 +279,6 @@ class BitcoinCashWallet extends CoinServiceAPI
return DerivePathType.bip44;
}
if (decodeBase58[0] == _network.scriptHash) {
// P2SH
return DerivePathType.bip49;
}
throw ArgumentError('Invalid version or Network mismatch');
} else {
try {
@ -419,15 +411,6 @@ class BitcoinCashWallet extends CoinServiceAPI
addrType = isar_models.AddressType.p2pkh;
addressString = bitbox.Address.toCashAddress(addressString);
break;
case DerivePathType.bip49:
addressString = P2SH(
data: PaymentData(
redeem: P2WPKH(data: data, network: _network).data),
network: _network)
.data
.address!;
addrType = isar_models.AddressType.p2sh;
break;
default:
throw Exception("DerivePathType $type not supported");
}
@ -518,7 +501,6 @@ class BitcoinCashWallet extends CoinServiceAPI
final deriveTypes = [
DerivePathType.bip44,
DerivePathType.bip49,
];
if (coin != Coin.bitcoincashTestnet) {
@ -1397,10 +1379,6 @@ class BitcoinCashWallet extends CoinServiceAPI
// P2PKH
_generateAddressForChain(0, 0, DerivePathType.bip44),
_generateAddressForChain(1, 0, DerivePathType.bip44),
// P2SH
_generateAddressForChain(0, 0, DerivePathType.bip49),
_generateAddressForChain(1, 0, DerivePathType.bip49),
]);
await db.putAddresses(initialAddresses);
@ -1408,7 +1386,7 @@ class BitcoinCashWallet extends CoinServiceAPI
Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info);
}
/// Generates a new internal or external chain address for the wallet using a BIP44 or BIP49 derivation path.
/// Generates a new internal or external chain address for the wallet using a BIP44 derivation path.
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
/// [index] - This can be any integer >= 0
Future<isar_models.Address> _generateAddressForChain(
@ -1449,17 +1427,6 @@ class BitcoinCashWallet extends CoinServiceAPI
addrType = isar_models.AddressType.p2pkh;
address = bitbox.Address.toCashAddress(address);
break;
case DerivePathType.bip49:
address = P2SH(
data: PaymentData(
redeem: P2WPKH(data: data, network: _network).data),
network: _network)
.data
.address!;
addrType = isar_models.AddressType.p2sh;
break;
case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH");
default:
throw Exception("DerivePathType $derivePathType not supported");
}
@ -1502,13 +1469,6 @@ class BitcoinCashWallet extends CoinServiceAPI
coinType = coin == Coin.bitcoincash ? "0" : "1";
purpose = "44";
break;
case DerivePathType.bip49:
type = isar_models.AddressType.p2sh;
coinType = coin == Coin.bitcoincash ? "145" : "1";
purpose = "49";
break;
case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH");
default:
throw Exception("DerivePathType $derivePathType not supported");
}
@ -1537,9 +1497,6 @@ class BitcoinCashWallet extends CoinServiceAPI
case DerivePathType.bch44:
key = "${walletId}_${chainId}DerivationsBch44P2PKH";
break;
case DerivePathType.bip49:
key = "${walletId}_${chainId}DerivationsP2SH";
break;
default:
throw UnsupportedError(
"${derivePathType.name} not supported by ${coin.prettyName}");
@ -2721,20 +2678,6 @@ class BitcoinCashWallet extends CoinServiceAPI
redeemScript = null;
break;
case DerivePathType.bip49:
final p2wpkh = P2WPKH(
data: PaymentData(
pubkey: Format.stringToUint8List(pubKey),
),
network: _network,
).data;
redeemScript = p2wpkh.output;
data = P2SH(
data: PaymentData(redeem: p2wpkh),
network: _network,
).data;
break;
default:
throw Exception("DerivePathType unsupported");
}

View file

@ -12,8 +12,8 @@ import 'package:stackwallet/services/event_bus/events/global/updated_in_backgrou
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/services/mixins/xpubable.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
@ -252,7 +252,8 @@ class Manager with ChangeNotifier {
);
}
bool get hasXPub => _currentWallet is XPubAble;
// TODO: re enable once xpubs have been redone
bool get hasXPub => false; //_currentWallet is XPubAble;
Future<String> get xpub async {
if (!hasXPub) {

View file

@ -103,6 +103,7 @@ class StackColors extends ThemeExtension<StackColors> {
// icons
final Color bottomNavIconBack;
final Color bottomNavIconIcon;
final Color bottomNavIconIconHighlighted;
final Color topNavIconPrimary;
final Color topNavIconGreen;
final Color topNavIconYellow;
@ -281,6 +282,7 @@ class StackColors extends ThemeExtension<StackColors> {
required this.snackBarTextInfo,
required this.bottomNavIconBack,
required this.bottomNavIconIcon,
required this.bottomNavIconIconHighlighted,
required this.topNavIconPrimary,
required this.topNavIconGreen,
required this.topNavIconYellow,
@ -441,6 +443,7 @@ class StackColors extends ThemeExtension<StackColors> {
snackBarTextInfo: colorTheme.snackBarTextInfo,
bottomNavIconBack: colorTheme.bottomNavIconBack,
bottomNavIconIcon: colorTheme.bottomNavIconIcon,
bottomNavIconIconHighlighted: colorTheme.bottomNavIconIconHighlighted,
topNavIconPrimary: colorTheme.topNavIconPrimary,
topNavIconGreen: colorTheme.topNavIconGreen,
topNavIconYellow: colorTheme.topNavIconYellow,
@ -603,6 +606,7 @@ class StackColors extends ThemeExtension<StackColors> {
Color? snackBarTextInfo,
Color? bottomNavIconBack,
Color? bottomNavIconIcon,
Color? bottomNavIconIconHighlighted,
Color? topNavIconPrimary,
Color? topNavIconGreen,
Color? topNavIconYellow,
@ -776,6 +780,8 @@ class StackColors extends ThemeExtension<StackColors> {
snackBarTextInfo: snackBarTextInfo ?? this.snackBarTextInfo,
bottomNavIconBack: bottomNavIconBack ?? this.bottomNavIconBack,
bottomNavIconIcon: bottomNavIconIcon ?? this.bottomNavIconIcon,
bottomNavIconIconHighlighted:
bottomNavIconIconHighlighted ?? this.bottomNavIconIconHighlighted,
topNavIconPrimary: topNavIconPrimary ?? this.topNavIconPrimary,
topNavIconGreen: topNavIconGreen ?? this.topNavIconGreen,
topNavIconYellow: topNavIconYellow ?? this.topNavIconYellow,
@ -1279,6 +1285,11 @@ class StackColors extends ThemeExtension<StackColors> {
other.bottomNavIconIcon,
t,
)!,
bottomNavIconIconHighlighted: Color.lerp(
bottomNavIconIconHighlighted,
other.bottomNavIconIconHighlighted,
t,
)!,
topNavIconPrimary: Color.lerp(
topNavIconPrimary,
other.topNavIconPrimary,

View file

@ -42,7 +42,7 @@ abstract class Constants {
// Enable Logger.print statements
static const bool disableLogger = false;
static const int currentHiveDbVersion = 8;
static const int currentDataVersion = 10;
static const int rescanV1 = 1;

View file

@ -3,9 +3,12 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart'
as isar_contact;
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';
@ -290,6 +293,48 @@ class DbVersionMigrator with WalletDB {
// try to continue migrating
return await migrate(8, secureStore: secureStore);
case 8:
// migrate
await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
final walletsService =
WalletsService(secureStorageInterface: secureStore);
final walletInfoList = await walletsService.walletNames;
await MainDB.instance.initMainDB();
for (final walletId in walletInfoList.keys) {
final info = walletInfoList[walletId]!;
if (info.coin == Coin.bitcoincash ||
info.coin == Coin.bitcoincashTestnet) {
final ids = await MainDB.instance
.getAddresses(walletId)
.filter()
.typeEqualTo(isar_models.AddressType.p2sh)
.idProperty()
.findAll();
await MainDB.instance.isar.writeTxn(() async {
await MainDB.instance.isar.addresses.deleteAll(ids);
});
}
}
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 9);
// try to continue migrating
return await migrate(9, secureStore: secureStore);
case 9:
// migrate
await _v9();
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 10);
// try to continue migrating
return await migrate(10, secureStore: secureStore);
default:
// finally return
return;
@ -447,4 +492,50 @@ class DbVersionMigrator with WalletDB {
}
}
}
Future<void> _v9() async {
final addressBookBox = await Hive.openBox<dynamic>(DB.boxNameAddressBook);
await MainDB.instance.initMainDB();
final keys = List<String>.from(addressBookBox.keys);
final contacts = keys
.map((id) => Contact.fromJson(
Map<String, dynamic>.from(
addressBookBox.get(id) as Map,
),
))
.toList(growable: false);
final List<isar_contact.ContactEntry> newContacts = [];
for (final contact in contacts) {
final List<isar_contact.ContactAddressEntry> newContactAddressEntries =
[];
for (final entry in contact.addresses) {
newContactAddressEntries.add(
isar_contact.ContactAddressEntry()
..coinName = entry.coin.name
..address = entry.address
..label = entry.label
..other = entry.other,
);
}
final newContact = isar_contact.ContactEntry(
name: contact.name,
addresses: newContactAddressEntries,
isFavorite: contact.isFavorite,
customId: contact.id,
);
newContacts.add(newContact);
}
await MainDB.instance.isar.writeTxn(() async {
await MainDB.instance.isar.contactEntrys.putAll(newContacts);
});
await addressBookBox.deleteFromDisk();
}
}

View file

@ -1,10 +1,13 @@
import 'dart:io';
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/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -14,8 +17,6 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/expandable.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import '../themes/theme_providers.dart';
class AddressBookCard extends ConsumerStatefulWidget {
const AddressBookCard({
Key? key,
@ -48,7 +49,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
@override
Widget build(BuildContext context) {
// provider hack to prevent trying to update widget with deleted contact
Contact? _contact;
ContactEntry? _contact;
try {
_contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(contactId)));
@ -81,7 +82,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
width: 32,
height: 32,
decoration: BoxDecoration(
color: contact.id == "default"
color: contact.customId == "default"
? Theme.of(context)
.extension<StackColors>()!
.myStackContactIconBG
@ -90,14 +91,16 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(32),
),
child: contact.id == "default"
child: contact.customId == "default"
? Center(
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
),
),
),
width: 20,
),
)
@ -176,7 +179,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
useSafeArea: true,
barrierDismissible: true,
builder: (_) => ContactPopUp(
contactId: contact.id,
contactId: contact.customId,
),
);
},

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
@ -47,7 +49,8 @@ class _LivingStackIconState extends ConsumerState<LivingStackIcon> {
child: AnimatedScale(
duration: const Duration(milliseconds: 200),
scale: _hovering ? 1.2 : 1,
child: SvgPicture.asset(
child: SvgPicture.file(
File(
ref.watch(
themeProvider.select(
(value) => value.assets.stackIcon,
@ -57,6 +60,7 @@ class _LivingStackIconState extends ConsumerState<LivingStackIcon> {
),
),
),
),
);
}
}

View file

@ -46,6 +46,12 @@ class RoundedContainer extends StatelessWidget {
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius * radiusMultiplier,
),
side: borderColor == null
? BorderSide.none
: BorderSide(
color: borderColor!,
width: 1.2,
),
),
onPressed: onPressed,
child: child,

View file

@ -14,7 +14,7 @@ class ExchangeNavIcon extends ConsumerWidget {
File(
ref.watch(
themeProvider.select(
(value) => value.assets.buy,
(value) => value.assets.exchange,
),
),
),

View file

@ -70,7 +70,8 @@ class WalletNavigationBarItem extends ConsumerWidget {
style: STextStyles.buttonSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.bottomNavText),
.bottomNavText,
),
),
],
),
@ -112,7 +113,11 @@ class WalletNavigationBarMoreItem extends ConsumerWidget {
child: Text(
data.label ?? "",
textAlign: TextAlign.center,
style: STextStyles.buttonSmall(context),
style: STextStyles.buttonSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.bottomNavText,
),
),
),
const SizedBox(

View file

@ -175,7 +175,7 @@ class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.infoItemIcons,
.bottomNavIconIconHighlighted,
),
crossFadeState: ref
.watch(walletNavBarMore.state)
@ -191,9 +191,9 @@ class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
STextStyles.buttonSmall(context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.bottomNavText),
.extension<StackColors>()!
.bottomNavText,
),
),
secondChild: Text(
"More",
@ -202,7 +202,7 @@ class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.infoItemIcons,
.bottomNavIconIconHighlighted,
),
),
crossFadeState: ref

View file

@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.7.8+170
version: 1.7.8+171
environment:
sdk: ">=2.17.0 <3.0.0"
@ -343,14 +343,9 @@ flutter:
# exchange icons
- assets/svg/exchange_icons/
# theme selectors
# - assets/svg/dark-theme.svg
# - assets/svg/light-mode.svg
# buy
- assets/svg/buy/
# lottie animations
# basic
- assets/lottie/test2.json

View file

@ -1,174 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart';
import 'package:hive_test/hive_test.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
void main() {
group("Empty DB tests", () {
setUp(() async {
await setUpTestHive();
await Hive.openBox<dynamic>(DB.boxNameAddressBook);
});
test("get empty contacts", () {
final service = AddressBookService();
expect(service.contacts, <Contact>[]);
});
test("get empty addressBookEntries", () async {
final service = AddressBookService();
expect(await service.addressBookEntries, <Contact>[]);
});
test("getContactById from empty db", () {
final service = AddressBookService();
expect(() => service.getContactById("some id"), throwsException);
});
tearDown(() async {
await tearDownTestHive();
});
});
group("Preloaded DB tests", () {
final contactA = Contact(name: "john", addresses: [], isFavorite: true);
final contactB = Contact(
name: "JANE",
addresses: [
const ContactAddressEntry(
coin: Coin.bitcoin,
address: "some btc address",
label: "rent",
),
],
isFavorite: false);
final contactC = Contact(
name: "Bill",
addresses: [
const ContactAddressEntry(
coin: Coin.monero,
address: "some xmr address",
label: "market",
),
const ContactAddressEntry(
coin: Coin.epicCash,
address: "some epic address",
label: "gas",
),
],
isFavorite: true);
setUp(() async {
await setUpTestHive();
await Hive.openBox<dynamic>(DB.boxNameAddressBook);
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contactA.id,
value: contactA.toMap());
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contactB.id,
value: contactB.toMap());
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contactC.id,
value: contactC.toMap());
});
test("getContactById with non existing ID", () {
final service = AddressBookService();
expect(() => service.getContactById("some id"), throwsException);
});
test("getContactById with existing ID", () {
final service = AddressBookService();
expect(
service.getContactById(contactA.id).toString(), contactA.toString());
});
test("get contacts", () {
final service = AddressBookService();
expect(service.contacts.toString(),
[contactC, contactB, contactA].toString());
});
test("get addressBookEntries", () async {
final service = AddressBookService();
expect((await service.addressBookEntries).toString(),
[contactC, contactB, contactA].toString());
});
test("search contacts", () async {
final service = AddressBookService();
final results = await service.search("j");
expect(results.toString(), [contactB, contactA].toString());
final results2 = await service.search("ja");
expect(results2.toString(), [contactB].toString());
final results3 = await service.search("john");
expect(results3.toString(), [contactA].toString());
final results4 = await service.search("po");
expect(results4.toString(), <Contact>[].toString());
final results5 = await service.search("");
expect(results5.toString(), [contactC, contactB, contactA].toString());
final results6 = await service.search("epic address");
expect(results6.toString(), [contactC].toString());
});
test("add new contact", () async {
final service = AddressBookService();
final contactD = Contact(name: "tim", addresses: [], isFavorite: true);
final result = await service.addContact(contactD);
expect(result, true);
expect(service.contacts.length, 4);
expect(
service.getContactById(contactD.id).toString(), contactD.toString());
});
test("add duplicate contact", () async {
final service = AddressBookService();
final result = await service.addContact(contactA);
expect(result, false);
expect(service.contacts.length, 3);
expect(service.contacts.toString(),
[contactC, contactB, contactA].toString());
});
test("edit contact", () async {
final service = AddressBookService();
final editedContact = contactB.copyWith(name: "Mike");
expect(await service.editContact(editedContact), true);
expect(service.contacts.length, 3);
expect(service.contacts.toString(),
[contactC, contactA, editedContact].toString());
});
test("remove existing contact", () async {
final service = AddressBookService();
await service.removeContact(contactB.id);
expect(service.contacts.length, 2);
expect(service.contacts.toString(), [contactC, contactA].toString());
});
test("remove non existing contact", () async {
final service = AddressBookService();
await service.removeContact("some id");
expect(service.contacts.length, 3);
expect(service.contacts.toString(),
[contactC, contactB, contactA].toString());
});
tearDown(() async {
await tearDownTestHive();
});
});
}

View file

@ -1,17 +1,35 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/models/notification_model.dart';
import 'package:stackwallet/notifications/notification_card.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_service.dart';
import 'package:stackwallet/utilities/assets.dart';
import '../sample_data/theme_json.dart';
import 'notification_card_test.mocks.dart';
@GenerateMocks([
ThemeService,
])
void main() {
testWidgets("test notification card", (widgetTester) async {
final key = UniqueKey();
final mockThemeService = MockThemeService();
final theme = StackTheme.fromJson(
json: lightThemeJsonMap,
applicationThemesDirectoryPath: "test",
);
when(mockThemeService.getTheme(themeId: "light")).thenAnswer(
(_) => theme,
);
final notificationCard = NotificationCard(
key: key,
notification: NotificationModel(
@ -27,14 +45,15 @@ void main() {
);
await widgetTester.pumpWidget(
MaterialApp(
ProviderScope(
overrides: [
pThemeService.overrideWithValue(mockThemeService),
],
child: MaterialApp(
theme: ThemeData(
extensions: [
StackColors.fromStackColorTheme(
StackTheme.fromJson(
json: lightThemeJsonMap,
applicationThemesDirectoryPath: "test",
),
theme,
),
],
),
@ -42,6 +61,7 @@ void main() {
child: notificationCard,
),
),
),
);
expect(find.byWidget(notificationCard), findsOneWidget);

View file

@ -0,0 +1,122 @@
// Mocks generated by Mockito 5.3.2 from annotations
// in stackwallet/test/notifications/notification_card_test.dart.
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i5;
import 'dart:typed_data' as _i6;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/db/isar/main_db.dart' as _i2;
import 'package:stackwallet/models/isar/stack_theme.dart' as _i4;
import 'package:stackwallet/themes/theme_service.dart' as _i3;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB {
_FakeMainDB_0(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [ThemeService].
///
/// See the documentation for Mockito's code generation for more information.
class MockThemeService extends _i1.Mock implements _i3.ThemeService {
MockThemeService() {
_i1.throwOnMissingStub(this);
}
@override
_i2.MainDB get db => (super.noSuchMethod(
Invocation.getter(#db),
returnValue: _FakeMainDB_0(
this,
Invocation.getter(#db),
),
) as _i2.MainDB);
@override
List<_i4.StackTheme> get installedThemes => (super.noSuchMethod(
Invocation.getter(#installedThemes),
returnValue: <_i4.StackTheme>[],
) as List<_i4.StackTheme>);
@override
void init(_i2.MainDB? db) => super.noSuchMethod(
Invocation.method(
#init,
[db],
),
returnValueForMissingStub: null,
);
@override
_i5.Future<void> install({required _i6.Uint8List? themeArchiveData}) =>
(super.noSuchMethod(
Invocation.method(
#install,
[],
{#themeArchiveData: themeArchiveData},
),
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
@override
_i5.Future<void> remove({required String? themeId}) => (super.noSuchMethod(
Invocation.method(
#remove,
[],
{#themeId: themeId},
),
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
@override
_i5.Future<bool> verifyInstalled({required String? themeId}) =>
(super.noSuchMethod(
Invocation.method(
#verifyInstalled,
[],
{#themeId: themeId},
),
returnValue: _i5.Future<bool>.value(false),
) as _i5.Future<bool>);
@override
_i5.Future<List<_i3.StackThemeMetaData>> fetchThemes() => (super.noSuchMethod(
Invocation.method(
#fetchThemes,
[],
),
returnValue: _i5.Future<List<_i3.StackThemeMetaData>>.value(
<_i3.StackThemeMetaData>[]),
) as _i5.Future<List<_i3.StackThemeMetaData>>);
@override
_i5.Future<_i6.Uint8List> fetchTheme(
{required _i3.StackThemeMetaData? themeMetaData}) =>
(super.noSuchMethod(
Invocation.method(
#fetchTheme,
[],
{#themeMetaData: themeMetaData},
),
returnValue: _i5.Future<_i6.Uint8List>.value(_i6.Uint8List(0)),
) as _i5.Future<_i6.Uint8List>);
@override
_i4.StackTheme? getTheme({required String? themeId}) =>
(super.noSuchMethod(Invocation.method(
#getTheme,
[],
{#themeId: themeId},
)) as _i4.StackTheme?);
}

View file

@ -91,6 +91,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"snack_bar_text_info": "0xFF002A78",
"bottom_nav_icon_back": "0xFFA2A2A2",
"bottom_nav_icon_icon": "0xFF232323",
"bottom_nav_icon_icon_highlighted": "0xFF232323",
"top_nav_icon_primary": "0xFF232323",
"top_nav_icon_green": "0xFF00A578",
"top_nav_icon_yellow": "0xFFF4C517",

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2;
import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: type=lint
@ -21,8 +21,8 @@ import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
_FakeContact_0(
class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContactEntry_0(
Object parent,
Invocation parentInvocation,
) : super(
@ -37,46 +37,43 @@ class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
class MockAddressBookService extends _i1.Mock
implements _i3.AddressBookService {
@override
List<_i2.Contact> get contacts => (super.noSuchMethod(
List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i2.Contact>[],
) as List<_i2.Contact>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue: <_i2.ContactEntry>[],
) as List<_i2.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i2.Contact getContactById(String? id) => (super.noSuchMethod(
_i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_0(
returnValue: _FakeContactEntry_0(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i2.Contact);
) as _i2.ContactEntry);
@override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod(
_i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue:
_i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override
bool matches(
String? term,
_i2.Contact? contact,
_i2.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -89,7 +86,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod(
_i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -97,7 +94,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>);
@override
_i4.Future<bool> editContact(_i2.Contact? editedContact) =>
_i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,

View file

@ -9,7 +9,7 @@ import 'dart:ui' as _i11;
import 'package:barcode_scan2/barcode_scan2.dart' as _i2;
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/contact_entry.dart' as _i3;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i14;
import 'package:stackwallet/models/models.dart' as _i5;
import 'package:stackwallet/services/address_book_service.dart' as _i10;
@ -40,8 +40,8 @@ class _FakeScanResult_0 extends _i1.SmartFake implements _i2.ScanResult {
);
}
class _FakeContact_1 extends _i1.SmartFake implements _i3.Contact {
_FakeContact_1(
class _FakeContactEntry_1 extends _i1.SmartFake implements _i3.ContactEntry {
_FakeContactEntry_1(
Object parent,
Invocation parentInvocation,
) : super(
@ -126,46 +126,43 @@ class MockBarcodeScannerWrapper extends _i1.Mock
class MockAddressBookService extends _i1.Mock
implements _i10.AddressBookService {
@override
List<_i3.Contact> get contacts => (super.noSuchMethod(
List<_i3.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i3.Contact>[],
) as List<_i3.Contact>);
@override
_i9.Future<List<_i3.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i9.Future<List<_i3.Contact>>.value(<_i3.Contact>[]),
) as _i9.Future<List<_i3.Contact>>);
returnValue: <_i3.ContactEntry>[],
) as List<_i3.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i3.Contact getContactById(String? id) => (super.noSuchMethod(
_i3.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_1(
returnValue: _FakeContactEntry_1(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i3.Contact);
) as _i3.ContactEntry);
@override
_i9.Future<List<_i3.Contact>> search(String? text) => (super.noSuchMethod(
_i9.Future<List<_i3.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i9.Future<List<_i3.Contact>>.value(<_i3.Contact>[]),
) as _i9.Future<List<_i3.Contact>>);
returnValue:
_i9.Future<List<_i3.ContactEntry>>.value(<_i3.ContactEntry>[]),
) as _i9.Future<List<_i3.ContactEntry>>);
@override
bool matches(
String? term,
_i3.Contact? contact,
_i3.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -178,7 +175,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i9.Future<bool> addContact(_i3.Contact? contact) => (super.noSuchMethod(
_i9.Future<bool> addContact(_i3.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -186,7 +183,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i9.Future<bool>.value(false),
) as _i9.Future<bool>);
@override
_i9.Future<bool> editContact(_i3.Contact? editedContact) =>
_i9.Future<bool> editContact(_i3.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,

View file

@ -8,7 +8,7 @@ import 'dart:ui' as _i9;
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/contact_entry.dart' as _i2;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/address_book_service.dart' as _i7;
@ -30,8 +30,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i11;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
_FakeContact_0(
class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContactEntry_0(
Object parent,
Invocation parentInvocation,
) : super(
@ -87,46 +87,43 @@ class _FakeAmount_4 extends _i1.SmartFake implements _i6.Amount {
class MockAddressBookService extends _i1.Mock
implements _i7.AddressBookService {
@override
List<_i2.Contact> get contacts => (super.noSuchMethod(
List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i2.Contact>[],
) as List<_i2.Contact>);
@override
_i8.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i8.Future<List<_i2.Contact>>);
returnValue: <_i2.ContactEntry>[],
) as List<_i2.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i2.Contact getContactById(String? id) => (super.noSuchMethod(
_i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_0(
returnValue: _FakeContactEntry_0(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i2.Contact);
) as _i2.ContactEntry);
@override
_i8.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod(
_i8.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i8.Future<List<_i2.Contact>>);
returnValue:
_i8.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i8.Future<List<_i2.ContactEntry>>);
@override
bool matches(
String? term,
_i2.Contact? contact,
_i2.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -139,7 +136,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i8.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod(
_i8.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -147,7 +144,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<bool> editContact(_i2.Contact? editedContact) =>
_i8.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,

View file

@ -8,7 +8,7 @@ import 'dart:ui' as _i9;
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/contact_entry.dart' as _i2;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12;
import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/address_book_service.dart' as _i7;
@ -28,8 +28,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i11;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
_FakeContact_0(
class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContactEntry_0(
Object parent,
Invocation parentInvocation,
) : super(
@ -85,46 +85,43 @@ class _FakeAmount_4 extends _i1.SmartFake implements _i6.Amount {
class MockAddressBookService extends _i1.Mock
implements _i7.AddressBookService {
@override
List<_i2.Contact> get contacts => (super.noSuchMethod(
List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i2.Contact>[],
) as List<_i2.Contact>);
@override
_i8.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i8.Future<List<_i2.Contact>>);
returnValue: <_i2.ContactEntry>[],
) as List<_i2.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i2.Contact getContactById(String? id) => (super.noSuchMethod(
_i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_0(
returnValue: _FakeContactEntry_0(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i2.Contact);
) as _i2.ContactEntry);
@override
_i8.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod(
_i8.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i8.Future<List<_i2.Contact>>);
returnValue:
_i8.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i8.Future<List<_i2.ContactEntry>>);
@override
bool matches(
String? term,
_i2.Contact? contact,
_i2.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -137,7 +134,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i8.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod(
_i8.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -145,7 +142,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<bool> editContact(_i2.Contact? editedContact) =>
_i8.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2;
import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i6;
import 'package:stackwallet/services/locale_service.dart' as _i7;
import 'package:stackwallet/services/notes_service.dart' as _i3;
@ -23,8 +23,8 @@ import 'package:stackwallet/services/notes_service.dart' as _i3;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
_FakeContact_0(
class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContactEntry_0(
Object parent,
Invocation parentInvocation,
) : super(
@ -141,46 +141,43 @@ class MockNotesService extends _i1.Mock implements _i3.NotesService {
class MockAddressBookService extends _i1.Mock
implements _i6.AddressBookService {
@override
List<_i2.Contact> get contacts => (super.noSuchMethod(
List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i2.Contact>[],
) as List<_i2.Contact>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue: <_i2.ContactEntry>[],
) as List<_i2.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i2.Contact getContactById(String? id) => (super.noSuchMethod(
_i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_0(
returnValue: _FakeContactEntry_0(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i2.Contact);
) as _i2.ContactEntry);
@override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod(
_i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue:
_i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override
bool matches(
String? term,
_i2.Contact? contact,
_i2.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -193,7 +190,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod(
_i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -201,7 +198,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>);
@override
_i4.Future<bool> editContact(_i2.Contact? editedContact) =>
_i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2;
import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i3;
import 'package:stackwallet/services/notes_service.dart' as _i6;
@ -22,8 +22,8 @@ import 'package:stackwallet/services/notes_service.dart' as _i6;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
_FakeContact_0(
class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContactEntry_0(
Object parent,
Invocation parentInvocation,
) : super(
@ -38,46 +38,43 @@ class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
class MockAddressBookService extends _i1.Mock
implements _i3.AddressBookService {
@override
List<_i2.Contact> get contacts => (super.noSuchMethod(
List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i2.Contact>[],
) as List<_i2.Contact>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue: <_i2.ContactEntry>[],
) as List<_i2.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i2.Contact getContactById(String? id) => (super.noSuchMethod(
_i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_0(
returnValue: _FakeContactEntry_0(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i2.Contact);
) as _i2.ContactEntry);
@override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod(
_i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue:
_i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override
bool matches(
String? term,
_i2.Contact? contact,
_i2.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -90,7 +87,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod(
_i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -98,7 +95,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>);
@override
_i4.Future<bool> editContact(_i2.Contact? editedContact) =>
_i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,

View file

@ -175,17 +175,6 @@ void main() async {
verifyNoMoreInteractions(cachedClient);
verifyNoMoreInteractions(tracker);
});
test("Multisig/P2SH address", () {
expect(
mainnetWallet?.addressType(
address: "3DYuVEmuKWQFxJcF7jDPhwPiXLTiNnyMFb"),
DerivePathType.bip49);
expect(secureStore.interactions, 0);
verifyNoMoreInteractions(client);
verifyNoMoreInteractions(cachedClient);
verifyNoMoreInteractions(tracker);
});
});
group("validate mainnet bitcoincash addresses", () {

View file

@ -5,18 +5,17 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/services/address_book_service.dart';
import '../sample_data/theme_json.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/address_book_card.dart';
import '../sample_data/theme_json.dart';
import 'address_book_card_test.mocks.dart';
class MockedFunctions extends Mock {
@ -27,18 +26,20 @@ class MockedFunctions extends Mock {
void main() {
testWidgets('test returns Contact Address Entry', (widgetTester) async {
final service = MockAddressBookService();
final applicationThemesDirectoryPath = "";
const applicationThemesDirectoryPath = "";
when(service.getContactById("default")).thenAnswer(
(realInvocation) => Contact(
(realInvocation) => ContactEntry(
name: "John Doe",
addresses: [
const ContactAddressEntry(
coin: Coin.bitcoincash,
address: "some bch address",
label: "Bills")
ContactAddressEntry()
..coinName = Coin.bitcoincash.name
..address = "some bch address"
..label = "Bills"
..other = null
],
isFavorite: true,
customId: '',
),
);

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2;
import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: type=lint
@ -21,8 +21,8 @@ import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
_FakeContact_0(
class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContactEntry_0(
Object parent,
Invocation parentInvocation,
) : super(
@ -41,46 +41,43 @@ class MockAddressBookService extends _i1.Mock
}
@override
List<_i2.Contact> get contacts => (super.noSuchMethod(
List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts),
returnValue: <_i2.Contact>[],
) as List<_i2.Contact>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue: <_i2.ContactEntry>[],
) as List<_i2.ContactEntry>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
_i2.Contact getContactById(String? id) => (super.noSuchMethod(
_i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method(
#getContactById,
[id],
),
returnValue: _FakeContact_0(
returnValue: _FakeContactEntry_0(
this,
Invocation.method(
#getContactById,
[id],
),
),
) as _i2.Contact);
) as _i2.ContactEntry);
@override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod(
_i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method(
#search,
[text],
),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
returnValue:
_i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override
bool matches(
String? term,
_i2.Contact? contact,
_i2.ContactEntry? contact,
) =>
(super.noSuchMethod(
Invocation.method(
@ -93,7 +90,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false,
) as bool);
@override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod(
_i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method(
#addContact,
[contact],
@ -101,7 +98,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>);
@override
_i4.Future<bool> editContact(_i2.Contact? editedContact) =>
_i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod(
Invocation.method(
#editContact,