mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-12 09:27:01 +00:00
convert token service to change notifier, add token cache per eth wallet, token balances, and fix routing issues
This commit is contained in:
parent
2287cd751e
commit
fcd8f01d93
7 changed files with 197 additions and 156 deletions
lib
71
lib/models/token_balance.dart
Normal file
71
lib/models/token_balance.dart
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:decimal/decimal.dart';
|
||||||
|
import 'package:stackwallet/models/balance.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
import 'package:stackwallet/utilities/format.dart';
|
||||||
|
|
||||||
|
class TokenBalance extends Balance {
|
||||||
|
TokenBalance({
|
||||||
|
required this.contractAddress,
|
||||||
|
required this.decimalPlaces,
|
||||||
|
required super.total,
|
||||||
|
required super.spendable,
|
||||||
|
required super.blockedTotal,
|
||||||
|
required super.pendingSpendable,
|
||||||
|
super.coin = Coin.ethereum,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String contractAddress;
|
||||||
|
final int decimalPlaces;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Decimal getTotal({bool includeBlocked = false}) =>
|
||||||
|
Format.satoshisToEthTokenAmount(
|
||||||
|
includeBlocked ? total : total - blockedTotal,
|
||||||
|
decimalPlaces,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Decimal getSpendable() => Format.satoshisToEthTokenAmount(
|
||||||
|
spendable,
|
||||||
|
decimalPlaces,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Decimal getPending() => Format.satoshisToEthTokenAmount(
|
||||||
|
pendingSpendable,
|
||||||
|
decimalPlaces,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Decimal getBlocked() => Format.satoshisToEthTokenAmount(
|
||||||
|
blockedTotal,
|
||||||
|
decimalPlaces,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toJsonIgnoreCoin() => jsonEncode({
|
||||||
|
"decimalPlaces": decimalPlaces,
|
||||||
|
"total": total,
|
||||||
|
"spendable": spendable,
|
||||||
|
"blockedTotal": blockedTotal,
|
||||||
|
"pendingSpendable": pendingSpendable,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory TokenBalance.fromJson(
|
||||||
|
String json,
|
||||||
|
String contractAddress,
|
||||||
|
int decimalPlaces,
|
||||||
|
) {
|
||||||
|
final decoded = jsonDecode(json);
|
||||||
|
return TokenBalance(
|
||||||
|
contractAddress: contractAddress,
|
||||||
|
decimalPlaces: decoded["decimalPlaces"] as int,
|
||||||
|
total: decoded["total"] as int,
|
||||||
|
spendable: decoded["spendable"] as int,
|
||||||
|
blockedTotal: decoded["blockedTotal"] as int,
|
||||||
|
pendingSpendable: decoded["pendingSpendable"] as int,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,6 @@ import 'package:stackwallet/utilities/format.dart';
|
||||||
import 'package:stackwallet/utilities/show_loading.dart';
|
import 'package:stackwallet/utilities/show_loading.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
class MyTokenSelectItem extends ConsumerWidget {
|
class MyTokenSelectItem extends ConsumerWidget {
|
||||||
const MyTokenSelectItem(
|
const MyTokenSelectItem(
|
||||||
|
@ -51,27 +50,25 @@ class MyTokenSelectItem extends ConsumerWidget {
|
||||||
BorderRadius.circular(Constants.size.circularBorderRadius),
|
BorderRadius.circular(Constants.size.circularBorderRadius),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final tokenService = EthereumTokenService(
|
ref.read(tokenServiceStateProvider.state).state =
|
||||||
|
EthereumTokenService(
|
||||||
token: token,
|
token: token,
|
||||||
secureStore: ref.read(secureStoreProvider),
|
secureStore: ref.read(secureStoreProvider),
|
||||||
ethWallet: ref.read(managerProvider).wallet as EthereumWallet,
|
ethWallet: ref.read(managerProvider).wallet as EthereumWallet,
|
||||||
tracker: TransactionNotificationTracker(
|
tracker: TransactionNotificationTracker(
|
||||||
walletId: ref.read(managerProvider).walletId),
|
walletId: ref.read(managerProvider).walletId,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await showLoading<void>(
|
await showLoading<void>(
|
||||||
whileFuture: tokenService.initializeExisting(),
|
whileFuture: ref.read(tokenServiceProvider)!.initializeExisting(),
|
||||||
context: context,
|
context: context,
|
||||||
message: "Loading ${token.name}",
|
message: "Loading ${token.name}",
|
||||||
);
|
);
|
||||||
|
|
||||||
await Navigator.of(context).pushNamed(
|
await Navigator.of(context).pushNamed(
|
||||||
TokenView.routeName,
|
TokenView.routeName,
|
||||||
arguments: Tuple3(
|
arguments: walletId,
|
||||||
walletId,
|
|
||||||
token,
|
|
||||||
tokenService,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,127 +1,50 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||||
import 'package:stackwallet/pages/token_view/sub_widgets/token_summary_info.dart';
|
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_summary_info.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/services/coins/manager.dart';
|
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||||
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
|
||||||
|
|
||||||
class TokenSummary extends StatelessWidget {
|
class TokenSummary extends ConsumerWidget {
|
||||||
const TokenSummary({
|
const TokenSummary({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.walletId,
|
required this.walletId,
|
||||||
required this.managerProvider,
|
|
||||||
required this.initialSyncStatus,
|
|
||||||
this.aspectRatio = 2.0,
|
|
||||||
this.minHeight = 100.0,
|
|
||||||
this.minWidth = 200.0,
|
|
||||||
this.maxHeight = 250.0,
|
|
||||||
this.maxWidth = 400.0,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final String walletId;
|
final String walletId;
|
||||||
final ChangeNotifierProvider<Manager> managerProvider;
|
|
||||||
final WalletSyncStatus initialSyncStatus;
|
|
||||||
|
|
||||||
final double aspectRatio;
|
|
||||||
final double minHeight;
|
|
||||||
final double minWidth;
|
|
||||||
final double maxHeight;
|
|
||||||
final double maxWidth;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return AspectRatio(
|
return RoundedContainer(
|
||||||
aspectRatio: aspectRatio,
|
color: const Color(0xFFE9EAFF), // todo: fix color
|
||||||
child: ConstrainedBox(
|
// color: Theme.of(context).extension<StackColors>()!.,
|
||||||
constraints: BoxConstraints(
|
|
||||||
minHeight: minHeight,
|
child: Column(
|
||||||
minWidth: minWidth,
|
children: [
|
||||||
maxHeight: maxHeight,
|
Text(
|
||||||
maxWidth: minWidth,
|
ref.watch(
|
||||||
),
|
walletsChangeNotifierProvider.select(
|
||||||
child: Stack(
|
(value) => value.getManager(walletId).walletName,
|
||||||
children: [
|
|
||||||
Consumer(
|
|
||||||
builder: (_, ref, __) {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.colorForCoin(ref.watch(
|
|
||||||
managerProvider.select((value) => value.coin))),
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Positioned.fill(
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Spacer(
|
|
||||||
flex: 5,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 6,
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.svg.ellipse1,
|
|
||||||
// fit: BoxFit.fitWidth,
|
|
||||||
// clipBehavior: Clip.none,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 25,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Positioned.fill(
|
style: STextStyles.label(context),
|
||||||
// child:
|
),
|
||||||
// Column(
|
Text(
|
||||||
// mainAxisAlignment: MainAxisAlignment.end,
|
ref.watch(tokenServiceProvider.select((value) => value!.balance
|
||||||
// children: [
|
.getTotal()
|
||||||
Align(
|
.toStringAsFixed(ref.watch(tokenServiceProvider
|
||||||
alignment: Alignment.bottomCenter,
|
.select((value) => value!.token.decimals))))),
|
||||||
child: Row(
|
style: STextStyles.label(context),
|
||||||
children: [
|
),
|
||||||
const Spacer(
|
Text(
|
||||||
flex: 1,
|
ref.watch(
|
||||||
),
|
walletsChangeNotifierProvider.select(
|
||||||
Expanded(
|
(value) => value.getManager(walletId).walletName,
|
||||||
flex: 3,
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.svg.ellipse2,
|
|
||||||
// fit: BoxFit.f,
|
|
||||||
// clipBehavior: Clip.none,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 13,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// ],
|
style: STextStyles.label(context),
|
||||||
// ),
|
),
|
||||||
// ),
|
],
|
||||||
Positioned.fill(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: TokenSummaryInfo(
|
|
||||||
walletId: walletId,
|
|
||||||
managerProvider: managerProvider,
|
|
||||||
initialSyncStatus: initialSyncStatus,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'package:event_bus/event_bus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
|
||||||
import 'package:stackwallet/pages/token_view/sub_widgets/token_transaction_list_widget.dart';
|
import 'package:stackwallet/pages/token_view/sub_widgets/token_transaction_list_widget.dart';
|
||||||
import 'package:stackwallet/pages/wallet_view/transaction_views/all_transactions_view.dart';
|
import 'package:stackwallet/pages/wallet_view/transaction_views/all_transactions_view.dart';
|
||||||
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
|
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
|
||||||
|
@ -15,13 +14,16 @@ import 'package:stackwallet/widgets/background.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||||
|
|
||||||
|
final tokenServiceStateProvider =
|
||||||
|
StateProvider<EthereumTokenService?>((ref) => null);
|
||||||
|
final tokenServiceProvider = ChangeNotifierProvider<EthereumTokenService?>(
|
||||||
|
(ref) => ref.watch(tokenServiceStateProvider));
|
||||||
|
|
||||||
/// [eventBus] should only be set during testing
|
/// [eventBus] should only be set during testing
|
||||||
class TokenView extends ConsumerStatefulWidget {
|
class TokenView extends ConsumerStatefulWidget {
|
||||||
const TokenView({
|
const TokenView({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.walletId,
|
required this.walletId,
|
||||||
required this.token,
|
|
||||||
required this.tokenService,
|
|
||||||
this.eventBus,
|
this.eventBus,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@ -29,8 +31,6 @@ class TokenView extends ConsumerStatefulWidget {
|
||||||
static const double navBarHeight = 65.0;
|
static const double navBarHeight = 65.0;
|
||||||
|
|
||||||
final String walletId;
|
final String walletId;
|
||||||
final EthToken token;
|
|
||||||
final EthereumTokenService tokenService;
|
|
||||||
final EventBus? eventBus;
|
final EventBus? eventBus;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -51,7 +51,6 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
debugPrint("BUILD: $runtimeType");
|
debugPrint("BUILD: $runtimeType");
|
||||||
// print("MY TOTAL BALANCE IS ${widget.token.totalBalance}");
|
|
||||||
|
|
||||||
return Background(
|
return Background(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
@ -67,7 +66,6 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
Assets.svg.iconFor(coin: Coin.ethereum),
|
Assets.svg.iconFor(coin: Coin.ethereum),
|
||||||
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
|
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
|
@ -76,14 +74,16 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.token.name,
|
ref.watch(tokenServiceProvider
|
||||||
|
.select((value) => value!.token.name)),
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.token.symbol,
|
ref.watch(tokenServiceProvider
|
||||||
|
.select((value) => value!.token.symbol)),
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
@ -167,7 +167,8 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TokenTransactionsList(
|
child: TokenTransactionsList(
|
||||||
tokenService: widget.tokenService,
|
tokenService: ref.watch(tokenServiceProvider
|
||||||
|
.select((value) => value!)),
|
||||||
walletId: widget.walletId,
|
walletId: widget.walletId,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -128,7 +128,6 @@ import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/nodes_
|
||||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/security_settings.dart';
|
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/security_settings.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart';
|
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart';
|
||||||
import 'package:stackwallet/services/coins/manager.dart';
|
import 'package:stackwallet/services/coins/manager.dart';
|
||||||
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
|
|
||||||
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
|
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
|
||||||
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
||||||
import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
|
import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
|
||||||
|
@ -1461,14 +1460,11 @@ class RouteGenerator {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
case TokenView.routeName:
|
case TokenView.routeName:
|
||||||
if (args is Tuple3<String, EthToken,
|
if (args is String) {
|
||||||
EthereumTokenService>) {
|
|
||||||
return getRoute(
|
return getRoute(
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
builder: (_) => TokenView(
|
builder: (_) => TokenView(
|
||||||
walletId: args.item1,
|
walletId: args,
|
||||||
token: args.item2,
|
|
||||||
tokenService: args.item3,
|
|
||||||
),
|
),
|
||||||
settings: RouteSettings(
|
settings: RouteSettings(
|
||||||
name: settings.name,
|
name: settings.name,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:decimal/decimal.dart';
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:ethereum_addresses/ethereum_addresses.dart';
|
import 'package:ethereum_addresses/ethereum_addresses.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
||||||
|
@ -9,10 +10,12 @@ import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
|
||||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
||||||
import 'package:stackwallet/models/node_model.dart';
|
import 'package:stackwallet/models/node_model.dart';
|
||||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||||
|
import 'package:stackwallet/models/token_balance.dart';
|
||||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
||||||
import 'package:stackwallet/services/ethereum/ethereum_api.dart';
|
import 'package:stackwallet/services/ethereum/ethereum_api.dart';
|
||||||
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
|
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
|
||||||
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
||||||
|
import 'package:stackwallet/services/mixins/eth_token_cache.dart';
|
||||||
import 'package:stackwallet/services/node_service.dart';
|
import 'package:stackwallet/services/node_service.dart';
|
||||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||||
|
@ -25,7 +28,7 @@ import 'package:stackwallet/utilities/logger.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
import 'package:web3dart/web3dart.dart' as web3dart;
|
import 'package:web3dart/web3dart.dart' as web3dart;
|
||||||
|
|
||||||
class EthereumTokenService {
|
class EthereumTokenService extends ChangeNotifier with EthTokenCache {
|
||||||
final EthToken token;
|
final EthToken token;
|
||||||
final EthereumWallet ethWallet;
|
final EthereumWallet ethWallet;
|
||||||
final TransactionNotificationTracker tracker;
|
final TransactionNotificationTracker tracker;
|
||||||
|
@ -48,11 +51,11 @@ class EthereumTokenService {
|
||||||
required this.tracker,
|
required this.tracker,
|
||||||
}) : _secureStore = secureStore {
|
}) : _secureStore = secureStore {
|
||||||
_contractAddress = web3dart.EthereumAddress.fromHex(token.contractAddress);
|
_contractAddress = web3dart.EthereumAddress.fromHex(token.contractAddress);
|
||||||
|
initCache(ethWallet.walletId, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Decimal> get availableBalance async {
|
TokenBalance get balance => _balance ??= getCachedBalance();
|
||||||
return await totalBalance;
|
TokenBalance? _balance;
|
||||||
}
|
|
||||||
|
|
||||||
Coin get coin => Coin.ethereum;
|
Coin get coin => Coin.ethereum;
|
||||||
|
|
||||||
|
@ -177,18 +180,6 @@ class EthereumTokenService {
|
||||||
|
|
||||||
final feeEstimate = await estimateFeeFor(satoshiAmount, fee);
|
final feeEstimate = await estimateFeeFor(satoshiAmount, fee);
|
||||||
|
|
||||||
bool isSendAll = false;
|
|
||||||
final balance =
|
|
||||||
Format.decimalAmountToSatoshis(await availableBalance, coin);
|
|
||||||
if (satoshiAmount == balance) {
|
|
||||||
isSendAll = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSendAll) {
|
|
||||||
//Send the full balance
|
|
||||||
satoshiAmount = balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> txData = {
|
Map<String, dynamic> txData = {
|
||||||
"fee": feeEstimate,
|
"fee": feeEstimate,
|
||||||
"feeInWei": fee,
|
"feeInWei": fee,
|
||||||
|
@ -205,6 +196,7 @@ class EthereumTokenService {
|
||||||
if (!_refreshLock) {
|
if (!_refreshLock) {
|
||||||
_refreshLock = true;
|
_refreshLock = true;
|
||||||
try {
|
try {
|
||||||
|
await refreshCachedBalance();
|
||||||
await _refreshTransactions();
|
await _refreshTransactions();
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logging.instance.log(
|
Logging.instance.log(
|
||||||
|
@ -213,22 +205,33 @@ class EthereumTokenService {
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
_refreshLock = false;
|
_refreshLock = false;
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Decimal> get totalBalance async {
|
Future<void> refreshCachedBalance() async {
|
||||||
final balanceRequest = await _client.call(
|
final balanceRequest = await _client.call(
|
||||||
contract: _contract,
|
contract: _contract,
|
||||||
function: _balanceFunction,
|
function: _balanceFunction,
|
||||||
params: [_credentials.address]);
|
params: [_credentials.address]);
|
||||||
|
|
||||||
String balance = balanceRequest.first.toString();
|
print("==========================================");
|
||||||
final balanceInDecimal = Format.satoshisToEthTokenAmount(
|
print("balanceRequest: $balanceRequest");
|
||||||
int.parse(balance),
|
print("==========================================");
|
||||||
token.decimals,
|
|
||||||
|
String _balance = balanceRequest.first.toString();
|
||||||
|
|
||||||
|
final newBalance = TokenBalance(
|
||||||
|
contractAddress: token.contractAddress,
|
||||||
|
total: int.parse(_balance),
|
||||||
|
spendable: int.parse(_balance),
|
||||||
|
blockedTotal: 0,
|
||||||
|
pendingSpendable: 0,
|
||||||
|
decimalPlaces: token.decimals,
|
||||||
);
|
);
|
||||||
return Decimal.parse(balanceInDecimal.toString());
|
await updateCachedBalance(newBalance);
|
||||||
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Transaction>> get transactions => ethWallet.db
|
Future<List<Transaction>> get transactions => ethWallet.db
|
||||||
|
|
50
lib/services/mixins/eth_token_cache.dart
Normal file
50
lib/services/mixins/eth_token_cache.dart
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import 'package:stackwallet/hive/db.dart';
|
||||||
|
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
||||||
|
import 'package:stackwallet/models/token_balance.dart';
|
||||||
|
|
||||||
|
abstract class _Keys {
|
||||||
|
static String tokenBalance(String contractAddress) {
|
||||||
|
return "tokenBalanceCache_$contractAddress";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin EthTokenCache {
|
||||||
|
late final String _walletId;
|
||||||
|
late final EthToken _token;
|
||||||
|
|
||||||
|
void initCache(String walletId, EthToken token) {
|
||||||
|
_walletId = walletId;
|
||||||
|
_token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// token balance cache
|
||||||
|
TokenBalance getCachedBalance() {
|
||||||
|
final jsonString = DB.instance.get<dynamic>(
|
||||||
|
boxName: _walletId,
|
||||||
|
key: _Keys.tokenBalance(_token.contractAddress),
|
||||||
|
) as String?;
|
||||||
|
if (jsonString == null) {
|
||||||
|
return TokenBalance(
|
||||||
|
contractAddress: _token.contractAddress,
|
||||||
|
decimalPlaces: _token.decimals,
|
||||||
|
total: 0,
|
||||||
|
spendable: 0,
|
||||||
|
blockedTotal: 0,
|
||||||
|
pendingSpendable: 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return TokenBalance.fromJson(
|
||||||
|
jsonString,
|
||||||
|
_token.contractAddress,
|
||||||
|
_token.decimals,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateCachedBalance(TokenBalance balance) async {
|
||||||
|
await DB.instance.put<dynamic>(
|
||||||
|
boxName: _walletId,
|
||||||
|
key: _Keys.tokenBalance(_token.contractAddress),
|
||||||
|
value: balance.toJsonIgnoreCoin(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue