mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Cw 1539 lightning enhancements (#3400)
* feat: add Lightning transaction URL support in transaction details view model * fix: update currency selection logic in WalletAddressListViewModel and ReceivePage * feat: integrate computed transaction amount and fee getters in TransactionDetailsViewModel, refactor CopyWrapper logic in TransactionDetailsModal * refactor: apply lint rules * refactor: apply lint rules and improve LNURL handling with new methods for withdrawal requests and error checks * auto-reformat * fix: receive_page regression * fix: Withdraw lightning to other btc wallet gives LN address * chore: update .lock files [skip ci] --------- Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com> Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
co-authored by
Robert Malikowski
Omar Hatem
parent
28c2cc152e
commit
03edd658a5
@@ -1,34 +1,36 @@
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/transaction_expandable_list_item.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/widgets/textfield_list_row.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/list_row.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_expandable_list.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_picker_list.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
|
||||
import 'package:cake_wallet/view_model/transaction_details_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import "package:cake_wallet/core/execution_state.dart";
|
||||
import "package:cake_wallet/generated/i18n.dart";
|
||||
import "package:cake_wallet/src/screens/base_page.dart";
|
||||
import "package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart";
|
||||
import "package:cake_wallet/src/screens/transaction_details/standart_list_item.dart";
|
||||
import "package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart";
|
||||
import "package:cake_wallet/src/screens/transaction_details/transaction_expandable_list_item.dart";
|
||||
import "package:cake_wallet/src/screens/transaction_details/widgets/textfield_list_row.dart";
|
||||
import "package:cake_wallet/src/widgets/alert_with_one_action.dart";
|
||||
import "package:cake_wallet/src/widgets/alert_with_two_actions.dart";
|
||||
import "package:cake_wallet/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart";
|
||||
import "package:cake_wallet/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart";
|
||||
import "package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart";
|
||||
import "package:cake_wallet/src/widgets/list_row.dart";
|
||||
import "package:cake_wallet/src/widgets/primary_button.dart";
|
||||
import "package:cake_wallet/src/widgets/standard_expandable_list.dart";
|
||||
import "package:cake_wallet/src/widgets/standard_list.dart";
|
||||
import "package:cake_wallet/src/widgets/standard_picker_list.dart";
|
||||
import "package:cake_wallet/utils/show_bar.dart";
|
||||
import "package:cake_wallet/utils/show_pop_up.dart";
|
||||
import "package:cake_wallet/view_model/send/send_view_model_state.dart";
|
||||
import "package:cake_wallet/view_model/transaction_details_view_model.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter/services.dart";
|
||||
import "package:flutter_mobx/flutter_mobx.dart";
|
||||
import "package:mobx/mobx.dart";
|
||||
|
||||
class RBFDetailsPage extends BasePage {
|
||||
RBFDetailsPage({required this.transactionDetailsViewModel, required this.rawTransaction}) {
|
||||
transactionDetailsViewModel.addBumpFeesListItems(
|
||||
transactionDetailsViewModel.transactionInfo, rawTransaction);
|
||||
transactionDetailsViewModel.transactionInfo,
|
||||
rawTransaction,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -46,70 +48,70 @@ class RBFDetailsPage extends BasePage {
|
||||
children: [
|
||||
Expanded(
|
||||
child: SectionStandardList(
|
||||
sectionCount: 1,
|
||||
itemCounter: (int _) => transactionDetailsViewModel.RBFListItems.length,
|
||||
itemBuilder: (__, index) {
|
||||
final item = transactionDetailsViewModel.RBFListItems[index];
|
||||
sectionCount: 1,
|
||||
itemCounter: (_) => transactionDetailsViewModel.rbfListItems.length,
|
||||
itemBuilder: (__, index) {
|
||||
final item = transactionDetailsViewModel.rbfListItems[index];
|
||||
|
||||
if (item is StandartListItem) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: item.value));
|
||||
showBar<void>(context, S.of(context).transaction_details_copied(item.title));
|
||||
},
|
||||
child: ListRow(title: '${item.title}:', value: item.value),
|
||||
);
|
||||
}
|
||||
if (item is StandartListItem) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: item.value));
|
||||
showBar<void>(context, S.of(context).transaction_details_copied(item.title));
|
||||
},
|
||||
child: ListRow(title: "${item.title}:", value: item.value),
|
||||
);
|
||||
}
|
||||
|
||||
if (item is StandardExpandableListItem) {
|
||||
return StandardExpandableList(
|
||||
title: '${item.title}: ${item.expandableItems.length}',
|
||||
expandableItems: item.expandableItems,
|
||||
);
|
||||
}
|
||||
if (item is StandardExpandableListItem) {
|
||||
return StandardExpandableList(
|
||||
title: "${item.title}: ${item.expandableItems.length}",
|
||||
expandableItems: item.expandableItems,
|
||||
);
|
||||
}
|
||||
|
||||
if (item is StandardPickerListItem) {
|
||||
return StandardPickerList(
|
||||
title: item.title,
|
||||
value: item.value,
|
||||
items: item.items,
|
||||
displayItem: item.displayItem,
|
||||
onSliderChanged: item.onSliderChanged,
|
||||
onItemSelected: item.onItemSelected,
|
||||
selectedIdx: item.selectedIdx,
|
||||
customItemIndex: item.customItemIndex,
|
||||
customValue: item.customValue,
|
||||
maxValue: item.maxValue,
|
||||
);
|
||||
}
|
||||
if (item is StandardPickerListItem) {
|
||||
return StandardPickerList(
|
||||
title: item.title,
|
||||
value: item.value,
|
||||
items: item.items,
|
||||
displayItem: item.displayItem,
|
||||
onSliderChanged: item.onSliderChanged,
|
||||
onItemSelected: item.onItemSelected,
|
||||
selectedIdx: item.selectedIdx,
|
||||
customItemIndex: item.customItemIndex,
|
||||
customValue: item.customValue,
|
||||
maxValue: item.maxValue,
|
||||
);
|
||||
}
|
||||
|
||||
if (item is TextFieldListItem) {
|
||||
return TextFieldListRow(
|
||||
title: item.title,
|
||||
value: item.value,
|
||||
onSubmitted: item.onSubmitted,
|
||||
);
|
||||
}
|
||||
if (item is TextFieldListItem) {
|
||||
return TextFieldListRow(
|
||||
title: item.title,
|
||||
value: item.value,
|
||||
onSubmitted: item.onSubmitted,
|
||||
);
|
||||
}
|
||||
|
||||
return Container();
|
||||
}),
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Observer(
|
||||
builder: (_) => LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
transactionDetailsViewModel
|
||||
.replaceByFee(transactionDetailsViewModel.newFee.toString());
|
||||
},
|
||||
text: S.of(context).send,
|
||||
isLoading:
|
||||
transactionDetailsViewModel.sendViewModel.state is IsExecutingState,
|
||||
isDisabled: transactionDetailsViewModel.sendViewModel.state
|
||||
is ExecutedSuccessfullyState,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
))),
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Observer(
|
||||
builder: (_) => LoadingPrimaryButton(
|
||||
onPressed: () => transactionDetailsViewModel
|
||||
.replaceByFee(transactionDetailsViewModel.newFee.toString()),
|
||||
text: S.of(context).send,
|
||||
isLoading: transactionDetailsViewModel.sendViewModel.state is IsExecutingState,
|
||||
isDisabled:
|
||||
transactionDetailsViewModel.sendViewModel.state is ExecutedSuccessfullyState,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -121,7 +123,7 @@ class RBFDetailsPage extends BasePage {
|
||||
return;
|
||||
}
|
||||
|
||||
reaction((_) => transactionDetailsViewModel.sendViewModel.state, (ExecutionState state) {
|
||||
reaction((_) => transactionDetailsViewModel.sendViewModel.state, (state) {
|
||||
if (state is! IsExecutingState &&
|
||||
loadingBottomSheetContext != null &&
|
||||
loadingBottomSheetContext!.mounted) {
|
||||
@@ -131,35 +133,35 @@ class RBFDetailsPage extends BasePage {
|
||||
if (state is FailureState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext popupContext) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(popupContext).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(popupContext).ok,
|
||||
buttonAction: () => Navigator.of(popupContext).pop());
|
||||
});
|
||||
context: context,
|
||||
builder: (popupContext) => AlertWithOneAction(
|
||||
alertTitle: S.of(popupContext).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(popupContext).ok,
|
||||
buttonAction: () => Navigator.of(popupContext).pop(),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
if (state is AwaitingConfirmationState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext popupContext) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: state.title ?? '',
|
||||
alertContent: state.message ?? '',
|
||||
rightButtonText: S.of(context).ok,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () {
|
||||
state.onConfirm?.call();
|
||||
Navigator.of(popupContext).pop();
|
||||
},
|
||||
actionLeftButton: () {
|
||||
state.onCancel?.call();
|
||||
Navigator.of(popupContext).pop();
|
||||
});
|
||||
});
|
||||
context: context,
|
||||
builder: (popupContext) => AlertWithTwoActions(
|
||||
alertTitle: state.title ?? "",
|
||||
alertContent: state.message ?? "",
|
||||
rightButtonText: S.of(context).ok,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () {
|
||||
state.onConfirm?.call();
|
||||
Navigator.of(popupContext).pop();
|
||||
},
|
||||
actionLeftButton: () {
|
||||
state.onCancel?.call();
|
||||
Navigator.of(popupContext).pop();
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,7 +171,7 @@ class RBFDetailsPage extends BasePage {
|
||||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
isDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
builder: (context) {
|
||||
loadingBottomSheetContext = context;
|
||||
return LoadingBottomSheet(
|
||||
titleText: S.of(context).generating_transaction,
|
||||
@@ -187,42 +189,42 @@ class RBFDetailsPage extends BasePage {
|
||||
context: context,
|
||||
isDismissible: false,
|
||||
isScrollControlled: true,
|
||||
builder: (BuildContext bottomSheetContext) {
|
||||
return ConfirmSendingBottomSheet(
|
||||
key: ValueKey('rbf_confirm_sending_bottom_sheet'),
|
||||
titleText: S.of(bottomSheetContext).confirm_transaction,
|
||||
isSlideActionEnabled: transactionDetailsViewModel.sendViewModel.isReadyForSend,
|
||||
walletType: transactionDetailsViewModel.sendViewModel.walletType,
|
||||
titleIconPath:
|
||||
transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency.iconPath,
|
||||
currency: transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency,
|
||||
amount: S.of(bottomSheetContext).send_amount,
|
||||
amountValue:
|
||||
transactionDetailsViewModel.sendViewModel.pendingTransaction!.amountFormatted,
|
||||
fiatAmountValue: transactionDetailsViewModel
|
||||
.sendViewModel.pendingTransactionFiatAmountFormatted,
|
||||
fee: S.of(bottomSheetContext).send_fee,
|
||||
feeValue:
|
||||
transactionDetailsViewModel.sendViewModel.pendingTransaction!.feeFormatted,
|
||||
feeFiatAmount: transactionDetailsViewModel
|
||||
.sendViewModel.pendingTransactionFeeFiatAmountFormatted,
|
||||
outputs: transactionDetailsViewModel.sendViewModel.outputs,
|
||||
footerType: FooterType.slideActionButton,
|
||||
accessibleNavigationModeSlideActionButtonText: S.of(context).send,
|
||||
onSlideActionComplete: () async {
|
||||
Navigator.of(bottomSheetContext).pop();
|
||||
await transactionDetailsViewModel.sendViewModel.commitTransaction(context);
|
||||
try {
|
||||
builder: (bottomSheetContext) => ConfirmSendingBottomSheet(
|
||||
key: const ValueKey("rbf_confirm_sending_bottom_sheet"),
|
||||
titleText: S.of(bottomSheetContext).confirm_transaction,
|
||||
isSlideActionEnabled: transactionDetailsViewModel.sendViewModel.isReadyForSend,
|
||||
walletType: transactionDetailsViewModel.sendViewModel.walletType,
|
||||
titleIconPath:
|
||||
transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency.iconPath,
|
||||
currency: transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency,
|
||||
amount: S.of(bottomSheetContext).send_amount,
|
||||
amountValue:
|
||||
transactionDetailsViewModel.sendViewModel.pendingTransaction!.amountFormatted,
|
||||
fiatAmountValue:
|
||||
transactionDetailsViewModel.sendViewModel.pendingTransactionFiatAmountFormatted,
|
||||
fee: S.of(bottomSheetContext).send_fee,
|
||||
feeValue:
|
||||
transactionDetailsViewModel.sendViewModel.pendingTransaction!.feeFormatted,
|
||||
feeFiatAmount: transactionDetailsViewModel
|
||||
.sendViewModel.pendingTransactionFeeFiatAmountFormatted,
|
||||
outputs: transactionDetailsViewModel.sendViewModel.outputs,
|
||||
footerType: FooterType.slideActionButton,
|
||||
accessibleNavigationModeSlideActionButtonText: S.of(context).send,
|
||||
onSlideActionComplete: () async {
|
||||
Navigator.of(bottomSheetContext).pop();
|
||||
await transactionDetailsViewModel.sendViewModel.commitTransaction(context);
|
||||
try {
|
||||
if (bottomSheetContext.mounted) {
|
||||
Navigator.of(bottomSheetContext).pop();
|
||||
} catch (_) {}
|
||||
},
|
||||
change: transactionDetailsViewModel.sendViewModel.pendingTransaction!.change,
|
||||
amountParsingProxy: transactionDetailsViewModel.sendViewModel.amountParsingProxy,
|
||||
);
|
||||
},
|
||||
}
|
||||
} catch (_) {}
|
||||
},
|
||||
change: transactionDetailsViewModel.sendViewModel.pendingTransaction!.change,
|
||||
amountParsingProxy: transactionDetailsViewModel.sendViewModel.amountParsingProxy,
|
||||
),
|
||||
);
|
||||
if (result == null) {
|
||||
transactionDetailsViewModel.sendViewModel.dismissTransaction();
|
||||
await transactionDetailsViewModel.sendViewModel.dismissTransaction();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -232,14 +234,14 @@ class RBFDetailsPage extends BasePage {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (context.mounted) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext popupContext) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(popupContext).sending,
|
||||
alertContent: S.of(popupContext).transaction_sent,
|
||||
buttonText: S.of(popupContext).ok,
|
||||
buttonAction: () => Navigator.of(popupContext).pop());
|
||||
});
|
||||
context: context,
|
||||
builder: (popupContext) => AlertWithOneAction(
|
||||
alertTitle: S.of(popupContext).sending,
|
||||
alertContent: S.of(popupContext).transaction_sent,
|
||||
buttonText: S.of(popupContext).ok,
|
||||
buttonAction: () => Navigator.of(popupContext).pop(),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user