handle getting currency via ticker or name a bit more nicely

This commit is contained in:
julian 2024-05-23 11:05:30 -06:00
parent 92802fc559
commit 3ee22cbbac
12 changed files with 148 additions and 94 deletions

View file

@ -13,21 +13,28 @@ abstract class AppConfig {
static List<CryptoCurrency> get coins => _supportedCoins;
static CryptoCurrency getCryptoCurrencyFor(String coinIdentifier) =>
coins.firstWhere(
(e) => e.identifier == coinIdentifier,
);
static CryptoCurrency? getCryptoCurrencyFor(String coinIdentifier) {
try {
return coins.firstWhere((e) => e.identifier == coinIdentifier);
} catch (_) {
return null;
}
}
static CryptoCurrency getCryptoCurrencyForTicker(
static CryptoCurrency? getCryptoCurrencyForTicker(
final String ticker, {
bool caseInsensitive = true,
}) {
final _ticker = caseInsensitive ? ticker.toLowerCase() : ticker;
return coins.firstWhere(
caseInsensitive
? (e) => e.ticker.toLowerCase() == _ticker && e is! FrostCurrency
: (e) => e.ticker == _ticker && e is! FrostCurrency,
);
try {
return coins.firstWhere(
caseInsensitive
? (e) => e.ticker.toLowerCase() == _ticker && e is! FrostCurrency
: (e) => e.ticker == _ticker && e is! FrostCurrency,
);
} catch (_) {
return null;
}
}
/// Fuzzy logic. Use with caution!!

View file

@ -557,7 +557,7 @@ class DbVersionMigrator with WalletDB {
final count = await MainDB.instance.getTransactions(walletId).count();
final crypto = AppConfig.getCryptoCurrencyFor(info.coinIdentifier);
final crypto = AppConfig.getCryptoCurrencyFor(info.coinIdentifier)!;
for (var i = 0; i < count; i += 50) {
final txns = await MainDB.instance

View file

@ -2,9 +2,8 @@ import 'dart:convert';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:isar/isar.dart';
import '../app_config.dart';
import 'hive/db.dart';
import 'isar/main_db.dart';
import '../models/isar/models/blockchain_data/v2/transaction_v2.dart';
import '../models/isar/models/isar_models.dart';
import '../utilities/flutter_secure_storage_interface.dart';
@ -13,6 +12,8 @@ import '../wallets/isar/models/token_wallet_info.dart';
import '../wallets/isar/models/wallet_info.dart';
import '../wallets/isar/models/wallet_info_meta.dart';
import '../wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
import 'hive/db.dart';
import 'isar/main_db.dart';
Future<void> migrateWalletsToIsar({
required SecureStorageInterface secureStore,
@ -167,8 +168,8 @@ Future<void> migrateWalletsToIsar({
coinName: old.coinIdentifier,
walletId: old.walletId,
name: old.name,
mainAddressType:
AppConfig.getCryptoCurrencyFor(old.coinIdentifier).primaryAddressType,
mainAddressType: AppConfig.getCryptoCurrencyFor(old.coinIdentifier)!
.primaryAddressType,
favouriteOrderIndex: favourites.indexOf(old.walletId),
cachedChainHeight: walletBox.get(
DBKeys.storedChainHeight,

View file

@ -43,7 +43,7 @@ class ContactAddressEntry {
factory ContactAddressEntry.fromJson(Map<String, dynamic> jsonObject) {
return ContactAddressEntry(
coin: AppConfig.getCryptoCurrencyFor(jsonObject["coin"] as String),
coin: AppConfig.getCryptoCurrencyFor(jsonObject["coin"] as String)!,
address: jsonObject["address"] as String,
label: jsonObject["label"] as String,
other: jsonObject["other"] as String?,

View file

@ -9,6 +9,7 @@
*/
import 'package:isar/isar.dart';
import '../../../app_config.dart';
import '../../../wallets/crypto_currency/crypto_currency.dart';
@ -102,7 +103,7 @@ class ContactAddressEntry {
late final String? other;
@ignore
CryptoCurrency get coin => AppConfig.getCryptoCurrencyFor(coinName);
CryptoCurrency get coin => AppConfig.getCryptoCurrencyFor(coinName)!;
ContactAddressEntry();

View file

@ -13,6 +13,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import '../../../app_config.dart';
import '../../../models/buy/response_objects/crypto.dart';
import '../../../themes/coin_icon_provider.dart';
@ -305,7 +306,7 @@ class CoinIconForTicker extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
try {
final coin = AppConfig.getCryptoCurrencyForTicker(ticker);
final coin = AppConfig.getCryptoCurrencyForTicker(ticker)!;
return SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),

View file

@ -12,6 +12,7 @@ import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import '../../../app_config.dart';
import '../../../models/exchange/response_objects/estimate.dart';
import '../../../providers/exchange/exchange_form_state_provider.dart';
@ -95,7 +96,8 @@ class _ExchangeOptionState extends ConsumerState<ExchangeOption> {
try {
decimals = AppConfig.getCryptoCurrencyForTicker(
receivingCurrency.ticker,
).fractionDigits;
)!
.fractionDigits;
} catch (_) {
decimals = 8; // some reasonable alternative
}

View file

@ -17,15 +17,14 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:tuple/tuple.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../app_config.dart';
import '../../models/exchange/change_now/exchange_transaction_status.dart';
import '../../models/isar/models/blockchain_data/transaction.dart';
import '../../models/isar/stack_theme.dart';
import '../../notifications/show_flush_bar.dart';
import 'edit_trade_note_view.dart';
import 'send_from_view.dart';
import '../wallet_view/transaction_views/edit_note_view.dart';
import '../wallet_view/transaction_views/transaction_details_view.dart';
import '../../providers/global/trades_service_provider.dart';
import '../../providers/providers.dart';
import '../../route_generator.dart';
@ -54,8 +53,10 @@ import '../../widgets/desktop/secondary_button.dart';
import '../../widgets/rounded_container.dart';
import '../../widgets/rounded_white_container.dart';
import '../../widgets/stack_dialog.dart';
import 'package:tuple/tuple.dart';
import 'package:url_launcher/url_launcher.dart';
import '../wallet_view/transaction_views/edit_note_view.dart';
import '../wallet_view/transaction_views/transaction_details_view.dart';
import 'edit_trade_note_view.dart';
import 'send_from_view.dart';
class TradeDetailsView extends ConsumerStatefulWidget {
const TradeDetailsView({
@ -281,7 +282,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
try {
coin = AppConfig.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
)!;
} catch (_) {
coin = AppConfig.getCryptoCurrencyByPrettyName(
trade.payInCurrency,
@ -382,7 +383,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
final coin =
AppConfig.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
)!;
final amount = sendAmount.toAmount(
fractionDigits: coin.fractionDigits,
);
@ -628,10 +629,9 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
CustomTextButton(
text: "View transaction",
onTap: () {
final CryptoCurrency coin =
AppConfig.getCryptoCurrencyForTicker(
final coin = AppConfig.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
)!;
if (isDesktop) {
Navigator.of(context).push(
@ -737,7 +737,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
text: address,
),
);
if (mounted) {
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.info,
@ -908,7 +908,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
text: address,
),
);
if (mounted) {
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.info,
@ -1276,7 +1276,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
onTap: () async {
final data = ClipboardData(text: trade.tradeId);
await clipboard.setData(data);
if (mounted) {
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.info,
@ -1384,7 +1384,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
try {
coin = AppConfig.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
)!;
} catch (_) {
coin = AppConfig.getCryptoCurrencyByPrettyName(
trade.payInCurrency,
@ -1415,7 +1415,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
}
class _Divider extends StatelessWidget {
const _Divider({Key? key}) : super(key: key);
const _Divider({super.key});
@override
Widget build(BuildContext context) {

View file

@ -16,6 +16,10 @@ import 'dart:typed_data';
import 'package:frostdart/frostdart.dart' as frost;
import 'package:isar/isar.dart';
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:tuple/tuple.dart';
import 'package:uuid/uuid.dart';
import 'package:wakelock/wakelock.dart';
import '../../../../../app_config.dart';
import '../../../../../db/hive/db.dart';
import '../../../../../db/isar/main_db.dart';
@ -52,9 +56,6 @@ import '../../../../../wallets/wallet/wallet.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart';
import 'package:tuple/tuple.dart';
import 'package:uuid/uuid.dart';
import 'package:wakelock/wakelock.dart';
class PreRestoreState {
final Set<String> walletIds;
@ -776,7 +777,7 @@ abstract class SWB {
final coin = AppConfig.getCryptoCurrencyFor(
walletbackup['coinName'] as String,
);
)!;
final walletName = walletbackup['name'] as String;
final walletId = oldToNewWalletIdMap[walletbackup["id"] as String]!;

View file

@ -14,15 +14,11 @@ import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:qr_flutter/qr_flutter.dart';
import '../../../app_config.dart';
import '../../../models/exchange/incomplete_exchange.dart';
import '../../../models/exchange/response_objects/trade.dart';
import '../../../pages/exchange_view/send_from_view.dart';
import 'subwidgets/desktop_step_1.dart';
import 'subwidgets/desktop_step_2.dart';
import 'subwidgets/desktop_step_3.dart';
import 'subwidgets/desktop_step_4.dart';
import '../subwidgets/desktop_exchange_steps_indicator.dart';
import '../../../providers/exchange/exchange_form_state_provider.dart';
import '../../../providers/global/trades_service_provider.dart';
import '../../../route_generator.dart';
@ -41,12 +37,18 @@ import '../../../widgets/desktop/primary_button.dart';
import '../../../widgets/desktop/secondary_button.dart';
import '../../../widgets/desktop/simple_desktop_dialog.dart';
import '../../../widgets/fade_stack.dart';
import '../subwidgets/desktop_exchange_steps_indicator.dart';
import 'subwidgets/desktop_step_1.dart';
import 'subwidgets/desktop_step_2.dart';
import 'subwidgets/desktop_step_3.dart';
import 'subwidgets/desktop_step_4.dart';
final ssss = StateProvider<IncompleteExchangeModel?>((_) => null);
final desktopExchangeModelProvider =
ChangeNotifierProvider<IncompleteExchangeModel?>(
(ref) => ref.watch(ssss.state).state);
(ref) => ref.watch(ssss.state).state,
);
class StepScaffold extends ConsumerStatefulWidget {
const StepScaffold({
@ -120,8 +122,9 @@ class _StepScaffoldState extends ConsumerState<StepScaffold> {
context: context,
barrierDismissible: true,
builder: (_) => SimpleDesktopDialog(
title: "Failed to create trade",
message: response.exception?.toString() ?? ""),
title: "Failed to create trade",
message: response.exception?.toString() ?? "",
),
),
);
}
@ -193,7 +196,7 @@ class _StepScaffoldState extends ConsumerState<StepScaffold> {
void sendFromStack() {
final trade = ref.read(desktopExchangeModelProvider)!.trade!;
final address = trade.payInAddress;
final coin = AppConfig.getCryptoCurrencyForTicker(trade.payInCurrency);
final coin = AppConfig.getCryptoCurrencyForTicker(trade.payInCurrency)!;
final amount = Decimal.parse(trade.payInAmount).toAmount(
fractionDigits: coin.fractionDigits,
);
@ -387,9 +390,11 @@ class _StepScaffoldState extends ConsumerState<StepScaffold> {
child: QrImageView(
// TODO: grab coin uri scheme from somewhere
// data: "${coin.uriScheme}:$receivingAddress",
data: ref.watch(desktopExchangeModelProvider
.select((value) =>
value!.trade!.payInAddress)),
data: ref.watch(
desktopExchangeModelProvider.select(
(value) => value!.trade!.payInAddress,
),
),
size: 290,
foregroundColor: Theme.of(context)
.extension<StackColors>()!

View file

@ -11,11 +11,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:tuple/tuple.dart';
import '../../../../app_config.dart';
import '../../../../models/contact_address_entry.dart';
import '../step_scaffold.dart';
import '../../subwidgets/desktop_choose_from_stack.dart';
import '../../../my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
import '../../../../providers/exchange/exchange_send_from_wallet_id_provider.dart';
import '../../../../providers/global/wallets_provider.dart';
import '../../../../themes/stack_colors.dart';
@ -32,7 +31,9 @@ import '../../../../widgets/icon_widgets/x_icon.dart';
import '../../../../widgets/rounded_white_container.dart';
import '../../../../widgets/stack_text_field.dart';
import '../../../../widgets/textfield_icon_button.dart';
import 'package:tuple/tuple.dart';
import '../../../my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
import '../../subwidgets/desktop_choose_from_stack.dart';
import '../step_scaffold.dart';
class DesktopStep2 extends ConsumerStatefulWidget {
const DesktopStep2({
@ -70,7 +71,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
try {
final coin = AppConfig.getCryptoCurrencyForTicker(
ref.read(desktopExchangeModelProvider)!.receiveTicker,
);
)!;
final info = await showDialog<Tuple2<String, String>?>(
context: context,
@ -96,14 +97,15 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
}
widget.enableNextChanged.call(
_toController.text.isNotEmpty && _refundController.text.isNotEmpty);
_toController.text.isNotEmpty && _refundController.text.isNotEmpty,
);
}
void selectRefundAddressFromStack() async {
try {
final coin = AppConfig.getCryptoCurrencyForTicker(
ref.read(desktopExchangeModelProvider)!.sendTicker,
);
)!;
final info = await showDialog<Tuple2<String, String>?>(
context: context,
@ -127,7 +129,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
Logging.instance.log("$e\n$s", level: LogLevel.Info);
}
widget.enableNextChanged.call(
_toController.text.isNotEmpty && _refundController.text.isNotEmpty);
_toController.text.isNotEmpty && _refundController.text.isNotEmpty,
);
}
void selectRecipientFromAddressBook() async {
@ -173,7 +176,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
_toController.text = entry.address;
ref.read(desktopExchangeModelProvider)!.recipientAddress = entry.address;
widget.enableNextChanged.call(
_toController.text.isNotEmpty && _refundController.text.isNotEmpty);
_toController.text.isNotEmpty && _refundController.text.isNotEmpty,
);
}
}
@ -220,7 +224,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
_refundController.text = entry.address;
ref.read(desktopExchangeModelProvider)!.refundAddress = entry.address;
widget.enableNextChanged.call(
_toController.text.isNotEmpty && _refundController.text.isNotEmpty);
_toController.text.isNotEmpty && _refundController.text.isNotEmpty,
);
}
}
@ -301,12 +306,17 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
Text(
"Recipient Wallet",
style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight),
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
),
if (isStackCoin(ref.watch(desktopExchangeModelProvider
.select((value) => value!.receiveTicker))))
if (isStackCoin(
ref.watch(
desktopExchangeModelProvider
.select((value) => value!.receiveTicker),
),
))
CustomTextButton(
text: "Choose from Stack",
onTap: selectRecipientAddressFromStack,
@ -339,8 +349,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
focusNode: _toFocusNode,
style: STextStyles.field(context),
onChanged: (value) {
widget.enableNextChanged.call(_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty);
widget.enableNextChanged.call(
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty,
);
},
decoration: standardInputDecoration(
"Enter the ${ref.watch(desktopExchangeModelProvider.select((value) => value!.receiveTicker.toUpperCase()))} payout address",
@ -365,21 +377,24 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
_toController.text.isNotEmpty
? TextFieldIconButton(
key: const Key(
"sendViewClearAddressFieldButtonKey"),
"sendViewClearAddressFieldButtonKey",
),
onTap: () {
_toController.text = "";
ref
.read(desktopExchangeModelProvider)!
.recipientAddress = _toController.text;
widget.enableNextChanged.call(
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty);
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty,
);
},
child: const XIcon(),
)
: TextFieldIconButton(
key: const Key(
"sendViewPasteAddressFieldButtonKey"),
"sendViewPasteAddressFieldButtonKey",
),
onTap: () async {
final ClipboardData? data = await clipboard
.getData(Clipboard.kTextPlain);
@ -391,8 +406,9 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
.read(desktopExchangeModelProvider)!
.recipientAddress = _toController.text;
widget.enableNextChanged.call(
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty);
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty,
);
}
},
child: _toController.text.isEmpty
@ -400,8 +416,12 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
: const XIcon(),
),
if (_toController.text.isEmpty &&
isStackCoin(ref.watch(desktopExchangeModelProvider
.select((value) => value!.receiveTicker))))
isStackCoin(
ref.watch(
desktopExchangeModelProvider
.select((value) => value!.receiveTicker),
),
))
TextFieldIconButton(
key: const Key("sendViewAddressBookButtonKey"),
onTap: selectRecipientFromAddressBook,
@ -433,12 +453,17 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
Text(
"Refund Wallet (required)",
style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight),
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
),
if (isStackCoin(ref.watch(desktopExchangeModelProvider
.select((value) => value!.sendTicker))))
if (isStackCoin(
ref.watch(
desktopExchangeModelProvider
.select((value) => value!.sendTicker),
),
))
CustomTextButton(
text: "Choose from Stack",
onTap: selectRefundAddressFromStack,
@ -470,8 +495,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
focusNode: _refundFocusNode,
style: STextStyles.field(context),
onChanged: (value) {
widget.enableNextChanged.call(_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty);
widget.enableNextChanged.call(
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty,
);
},
decoration: standardInputDecoration(
"Enter ${ref.watch(desktopExchangeModelProvider.select((value) => value!.sendTicker.toUpperCase()))} refund address",
@ -496,7 +523,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
_refundController.text.isNotEmpty
? TextFieldIconButton(
key: const Key(
"sendViewClearAddressFieldButtonKey"),
"sendViewClearAddressFieldButtonKey",
),
onTap: () {
_refundController.text = "";
ref
@ -504,14 +532,16 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
.refundAddress = _refundController.text;
widget.enableNextChanged.call(
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty);
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty,
);
},
child: const XIcon(),
)
: TextFieldIconButton(
key: const Key(
"sendViewPasteAddressFieldButtonKey"),
"sendViewPasteAddressFieldButtonKey",
),
onTap: () async {
final ClipboardData? data = await clipboard
.getData(Clipboard.kTextPlain);
@ -525,8 +555,9 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
.refundAddress = _refundController.text;
widget.enableNextChanged.call(
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty);
_toController.text.isNotEmpty &&
_refundController.text.isNotEmpty,
);
}
},
child: _refundController.text.isEmpty
@ -534,8 +565,12 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
: const XIcon(),
),
if (_refundController.text.isEmpty &&
isStackCoin(ref.watch(desktopExchangeModelProvider
.select((value) => value!.sendTicker))))
isStackCoin(
ref.watch(
desktopExchangeModelProvider
.select((value) => value!.sendTicker),
),
))
TextFieldIconButton(
key: const Key("sendViewAddressBookButtonKey"),
onTap: selectRefundFromAddressBook,

View file

@ -1,13 +1,14 @@
import 'dart:convert';
import 'package:isar/isar.dart';
import 'package:uuid/uuid.dart';
import '../../../app_config.dart';
import '../../../models/balance.dart';
import '../../../models/isar/models/blockchain_data/address.dart';
import '../../crypto_currency/crypto_currency.dart';
import '../isar_id_interface.dart';
import 'wallet_info_meta.dart';
import 'package:uuid/uuid.dart';
part 'wallet_info.g.dart';
@ -96,7 +97,7 @@ class WalletInfo implements IsarId {
}
@ignore
CryptoCurrency get coin => AppConfig.getCryptoCurrencyFor(coinName);
CryptoCurrency get coin => AppConfig.getCryptoCurrencyFor(coinName)!;
@ignore
Balance get cachedBalance {
@ -466,7 +467,7 @@ class WalletInfo implements IsarId {
) {
final coin = AppConfig.getCryptoCurrencyFor(
jsonObject["coin"] as String,
);
)!;
return WalletInfo(
coinName: coin.identifier,
walletId: jsonObject["id"] as String,