diff --git a/lib/pages/tabs/withdrawal_bundle_tab_page.dart b/lib/pages/tabs/withdrawal_bundle_tab_page.dart index e193b872..2d430b1e 100644 --- a/lib/pages/tabs/withdrawal_bundle_tab_page.dart +++ b/lib/pages/tabs/withdrawal_bundle_tab_page.dart @@ -10,6 +10,8 @@ import 'package:sidesail/config/this_sidechain.dart'; import 'package:sidesail/rpc/rpc_mainchain.dart'; import 'package:sidesail/rpc/rpc_sidechain.dart'; import 'package:sidesail/rpc/rpc_withdrawal_bundle.dart'; +import 'package:sidesail/pages/tabs/dashboard_tab_page.dart'; +import 'package:sidesail/widgets/containers/tabs/dashboard_tab_widgets.dart'; import 'package:stacked/stacked.dart'; @RoutePage() @@ -18,16 +20,61 @@ class WithdrawalBundleTabPage extends StatelessWidget { @override Widget build(BuildContext context) { - return SailPage( - title: 'Withdrawal bundles', - body: ViewModelBuilder.reactive( - viewModelBuilder: () => WithdrawalBundleTabPageViewModel(), - builder: ((context, viewModel, child) { - return SailText.primary13( - 'Withdrawal bundle status: ${viewModel.message}', - ); - }), - ), + return ViewModelBuilder.reactive( + viewModelBuilder: () => WithdrawalBundleTabPageViewModel(), + builder: ((context, viewModel, child) { + return SailPage( + title: 'Withdrawal bundles', + body: SingleChildScrollView( + child: Column( + children: [ + DashboardGroup( + title: 'Unbundled transactions', + children: [ + SailColumn( + spacing: 0, + withDivider: true, + crossAxisAlignment: CrossAxisAlignment.start, + children: viewModel.nextBundle?.withdrawals + .map( + (tx) => WithdrawalView( + withdrawal: tx, + ), + ) + .toList() ?? + [], + ), + ], + ), + const SailSpacing(SailStyleValues.padding30), + DashboardGroup( + title: 'Current withdrawal bundle', + endWidget: SailText.primary12( + [ + 'Created at block height ${viewModel.currentBundle?.blockHeight}', + '${viewModel.votes}/${viewModel.votesRequired} votes', + '${viewModel.currentBundle?.bundleSize}/${viewModel.currentBundle?.maxBundleSize} vbytes', + ].join(', '), + ), + children: [ + SailColumn( + spacing: 0, + withDivider: true, + crossAxisAlignment: CrossAxisAlignment.start, + children: viewModel.currentBundle?.withdrawals + .map( + (tx) => WithdrawalView(withdrawal: tx), + ) + .toList() ?? + [], + ), + ], + ), + ], + ), + ), + ); + }), ); } } @@ -36,14 +83,14 @@ class WithdrawalBundleTabPageViewModel extends BaseViewModel { SidechainRPC get _sidechain => GetIt.I.get(); MainchainRPC get _mainchain => GetIt.I.get(); + final searchController = TextEditingController(); + WithdrawalBundleTabPageViewModel() { _startWithdrawalBundleFetch(); } Timer? _withdrawalBundleTimer; - String? message; - WithdrawalBundle? currentBundle; FutureWithdrawalBundle? nextBundle; @@ -55,12 +102,10 @@ class WithdrawalBundleTabPageViewModel extends BaseViewModel { currentBundle = await _sidechain.currentWithdrawalBundle(); nextBundle = await _sidechain.nextWithdrawalBundle(); votes = await _mainchain.getWithdrawalBundleWorkScore(ThisSidechain.slot, currentBundle!.hash); - message = 'lookie, a bundle'; } on RPCException catch (err) { if (err.errorCode != RPCError.errNoWithdrawalBundle) { rethrow; } - message = 'No withdrawal bundle created. Need at least 10 withdrawals!'; } finally { notifyListeners(); } @@ -74,7 +119,55 @@ class WithdrawalBundleTabPageViewModel extends BaseViewModel { @override void dispose() { - _withdrawalBundleTimer?.cancel(); super.dispose(); + _withdrawalBundleTimer?.cancel(); + } +} + +class WithdrawalView extends StatefulWidget { + final Withdrawal withdrawal; + + const WithdrawalView({super.key, required this.withdrawal}); + + @override + State createState() => _WithdrawalViewState(); +} + +class _WithdrawalViewState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: SailStyleValues.padding15, + horizontal: SailStyleValues.padding10, + ), + child: SailColumn( + spacing: SailStyleValues.padding08, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleValueView( + width: 70, + icon: Tooltip( + message: 'Unconfirmed', + child: SailSVG.icon(SailSVGAsset.iconPending, width: 13), + ), + copyable: false, + label: 'TODO', + value: extractTitle(widget.withdrawal), + ), + ], + ), + ); + } + + String extractTitle(Withdrawal withdrawal) { + final title = '${(withdrawal.amountSatoshi / 100000000).toStringAsFixed(8)} SBTC'; + + return '$title to ${withdrawal.address}'; } }