Skip to content

Commit

Permalink
Add support for paying BOLT12 offers (#251)
Browse files Browse the repository at this point in the history
* feat: add support for paying BOLT 12 offers

* chore: export LnOfferPaymentPage route
  • Loading branch information
erdemyerebasmaz authored Dec 3, 2024
1 parent 8e971a7 commit 7ab710e
Show file tree
Hide file tree
Showing 8 changed files with 531 additions and 2 deletions.
10 changes: 10 additions & 0 deletions lib/app/routes/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@ Route<dynamic>? onGenerateRoute({
),
settings: settings,
);
case LnOfferPaymentPage.routeName:
return FadeInRoute<PrepareSendResponse?>(
builder: (BuildContext context) => BlocProvider<PaymentLimitsCubit>(
create: (BuildContext context) => PaymentLimitsCubit(ServiceInjector().breezSdkLiquid),
child: LnOfferPaymentPage(
lnOffer: settings.arguments as LNOffer,
),
),
settings: settings,
);
case LnUrlPaymentPage.routeName:
return FadeInRoute<PrepareLnUrlPayResponse?>(
builder: (BuildContext context) => BlocProvider<PaymentLimitsCubit>(
Expand Down
2 changes: 2 additions & 0 deletions lib/cubit/input/input_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class InputCubit extends Cubit<InputState> {
InputState result;
if (parsedInput is InputType_Bolt11) {
result = await handlePaymentRequest(parsedInput, source);
} else if (parsedInput is InputType_Bolt12Offer) {
result = InputState.bolt12Offer(parsedInput.offer, source);
} else if (parsedInput is InputType_LnUrlPay) {
result = InputState.lnUrlPay(parsedInput.data, source);
} else if (parsedInput is InputType_LnUrlWithdraw) {
Expand Down
33 changes: 32 additions & 1 deletion lib/cubit/input/input_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class InputState {
InputSource source,
) = LnInvoiceInputState;

const factory InputState.bolt12Offer(
LNOffer lnOffer,
InputSource source,
) = LnOfferInputState;

const factory InputState.lnUrlPay(
LnUrlPayRequestData data,
InputSource source,
Expand Down Expand Up @@ -92,7 +97,7 @@ class LnInvoiceInputState extends InputState {

@override
String toString() {
return 'InvoiceInputState{lnInvoice: $lnInvoice, source: $source}';
return 'LnInvoiceInputState{lnInvoice: $lnInvoice, source: $source}';
}

@override
Expand All @@ -107,6 +112,32 @@ class LnInvoiceInputState extends InputState {
int get hashCode => lnInvoice.hashCode ^ source.hashCode;
}

class LnOfferInputState extends InputState {
const LnOfferInputState(
this.lnOffer,
this.source,
) : super._();

final LNOffer lnOffer;
final InputSource source;

@override
String toString() {
return 'LnOfferInputState{lnInvoice: $lnOffer, source: $source}';
}

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is LnOfferInputState &&
runtimeType == other.runtimeType &&
lnOffer == other.lnOffer &&
source == other.source;

@override
int get hashCode => lnOffer.hashCode ^ source.hashCode;
}

class LnUrlPayInputState extends InputState {
const LnUrlPayInputState(
this.data,
Expand Down
37 changes: 37 additions & 0 deletions lib/handlers/input_handler/src/input_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class InputHandler extends Handler {

if (inputState is LnInvoiceInputState) {
return handleLnInvoice(context, inputState.lnInvoice);
} else if (inputState is LnOfferInputState) {
return handleLnOffer(context, inputState.lnOffer);
} else if (inputState is LnUrlPayInputState) {
return handlePayRequest(context, firstPaymentItemKey, inputState.data);
} else if (inputState is LnUrlWithdrawInputState) {
Expand Down Expand Up @@ -136,6 +138,41 @@ class InputHandler extends Handler {
});
}

Future<dynamic> handleLnOffer(BuildContext context, LNOffer lnOffer) async {
_logger.info('handle LNOffer $lnOffer');
final NavigatorState navigator = Navigator.of(context);
final PrepareSendResponse? prepareResponse = await navigator.pushNamed<PrepareSendResponse?>(
LnOfferPaymentPage.routeName,
arguments: lnOffer,
);
if (prepareResponse == null || !context.mounted) {
return Future<dynamic>.value();
}

// Show Processing Payment Dialog
return await showDialog(
useRootNavigator: false,
context: context,
barrierDismissible: false,
builder: (_) => ProcessingPaymentDialog(
isLnUrlPayment: true,
firstPaymentItemKey: firstPaymentItemKey,
paymentFunc: () async {
final PaymentsCubit paymentsCubit = context.read<PaymentsCubit>();
return await paymentsCubit.sendPayment(prepareResponse);
},
),
).then((dynamic result) {
if (result is String && context.mounted) {
showFlushbar(context, message: result);
}
// TODO(erdemyerebasmaz): Handle SendPaymentResponse results, return a SendPaymentResult to be handled by handleResult()
if (result is SendPaymentResponse) {
_logger.info('SendPaymentResponse result - payment status: ${result.payment.status}');
}
});
}

Future<dynamic> handleBitcoinAddress(BuildContext context, BitcoinAddressInputState inputState) async {
_logger.fine('handle bitcoin address $inputState');
if (inputState.source == InputSource.qrcodeReader) {
Expand Down
2 changes: 2 additions & 0 deletions lib/routes/send_payment/lightning/lightning.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'ln_invoice_payment_page.dart';
export 'ln_offer_payment_page.dart';
Loading

0 comments on commit 7ab710e

Please sign in to comment.