This commit is contained in:
Matthew Fosse 2024-03-06 22:10:40 -08:00
parent 8828262ee0
commit 3fd8430e83
8 changed files with 128 additions and 73 deletions

View file

@ -14,6 +14,7 @@ import 'package:cake_wallet/core/yat_service.dart';
import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/background_tasks.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart';
import 'package:cake_wallet/view_model/LightningSendViewModel.dart';
import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/receive_page_option.dart';
import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/lightning/lightning.dart'; import 'package:cake_wallet/lightning/lightning.dart';
@ -1205,10 +1206,16 @@ Future<void> setup({
getIt.registerFactory(() => NFTViewModel(appStore, getIt.get<BottomSheetService>())); getIt.registerFactory(() => NFTViewModel(appStore, getIt.get<BottomSheetService>()));
getIt.registerFactory<TorPage>(() => TorPage(getIt.get<AppStore>())); getIt.registerFactory<TorPage>(() => TorPage(getIt.get<AppStore>()));
getIt.registerFactory<LightningViewModel>(() => LightningViewModel( getIt.registerFactory<LightningViewModel>(
() => LightningViewModel(),
);
getIt.registerFactory<LightningSendViewModel>(
() => LightningSendViewModel(
settingsStore: getIt.get<SettingsStore>(), settingsStore: getIt.get<SettingsStore>(),
fiatConversionStore: getIt.get<FiatConversionStore>(), fiatConversionStore: getIt.get<FiatConversionStore>(),
)); ),
);
getIt.registerFactoryParam<LightningInvoicePageViewModel, void, void>((_, __) { getIt.registerFactoryParam<LightningInvoicePageViewModel, void, void>((_, __) {
return LightningInvoicePageViewModel( return LightningInvoicePageViewModel(
@ -1246,14 +1253,14 @@ Future<void> setup({
() => CryptoCurrency.btcln, () => CryptoCurrency.btcln,
), ),
authService: getIt.get<AuthService>(), authService: getIt.get<AuthService>(),
lightningViewModel: getIt.get<LightningViewModel>(), lightningSendViewModel: getIt.get<LightningSendViewModel>(),
); );
}); });
getIt.registerFactoryParam<LightningSendConfirmPage, LNInvoice, void>((LNInvoice invoice, _) { getIt.registerFactoryParam<LightningSendConfirmPage, LNInvoice, void>((LNInvoice invoice, _) {
return LightningSendConfirmPage( return LightningSendConfirmPage(
invoice: invoice, invoice: invoice,
lightningViewModel: getIt.get<LightningViewModel>(), lightningSendViewModel: getIt.get<LightningSendViewModel>(),
); );
}); });

View file

@ -169,18 +169,16 @@ class LightningInvoicePage extends BasePage {
Container(child: Center(child: CircularProgressIndicator()))); Container(child: Center(child: CircularProgressIndicator())));
} }
late String finalText; late String finalText;
int balance = (snapshot.data as List<int>)[2]; InvoiceSoftLimitsResult limits =
if (balance == 0) { snapshot.data as InvoiceSoftLimitsResult;
int min = (snapshot.data as List<int>)[0]; if (limits.balance == 0) {
finalText = S finalText = S
.of(context) .of(context)
.lightning_invoice_min(lightning!.satsToLightningString(min)); .lightning_invoice_min(lightning!.satsToLightningString(limits.min));
} else { } else {
int min = (snapshot.data as List<int>)[0];
int max = (snapshot.data as List<int>)[1];
finalText = S.of(context).lightning_invoice_min_max( finalText = S.of(context).lightning_invoice_min_max(
lightning!.satsToLightningString(min), lightning!.satsToLightningString(limits.min),
lightning!.satsToLightningString(max), lightning!.satsToLightningString(limits.max),
); );
} }

View file

@ -73,7 +73,7 @@ class LightningReceiveOnchainPage extends BasePage {
if (snapshot.data == null) { if (snapshot.data == null) {
return CircularProgressIndicator(); return CircularProgressIndicator();
} }
String data = (snapshot.data as List<String>)[0]; ReceiveOnchainResult results = snapshot.data as ReceiveOnchainResult;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
@ -99,7 +99,7 @@ class LightningReceiveOnchainPage extends BasePage {
() async { () async {
await Navigator.pushNamed(context, Routes.fullscreenQR, await Navigator.pushNamed(context, Routes.fullscreenQR,
arguments: QrViewData( arguments: QrViewData(
data: data, data: results.bitcoinAddress,
heroTag: heroTag, heroTag: heroTag,
)); ));
}, },
@ -127,7 +127,7 @@ class LightningReceiveOnchainPage extends BasePage {
color: Colors.white, color: Colors.white,
), ),
), ),
child: QrImage(data: data)), child: QrImage(data: results.bitcoinAddress)),
), ),
), ),
), ),
@ -144,7 +144,7 @@ class LightningReceiveOnchainPage extends BasePage {
builder: (context) => Observer( builder: (context) => Observer(
builder: (context) => GestureDetector( builder: (context) => GestureDetector(
onTap: () { onTap: () {
Clipboard.setData(ClipboardData(text: data)); Clipboard.setData(ClipboardData(text: results.bitcoinAddress));
showBar<void>(context, S.of(context).copied_to_clipboard); showBar<void>(context, S.of(context).copied_to_clipboard);
}, },
child: Row( child: Row(
@ -153,7 +153,7 @@ class LightningReceiveOnchainPage extends BasePage {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: Text( child: Text(
data, results.bitcoinAddress,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
@ -207,15 +207,13 @@ class LightningReceiveOnchainPage extends BasePage {
return Expanded( return Expanded(
child: Container(child: Center(child: CircularProgressIndicator()))); child: Container(child: Center(child: CircularProgressIndicator())));
} }
int min = int.parse((snapshot.data as List<String>)[1]); ReceiveOnchainResult results = snapshot.data as ReceiveOnchainResult;
int max = int.parse((snapshot.data as List<String>)[2]);
int fee = int.parse((snapshot.data as List<String>)[3]);
return Expanded( return Expanded(
child: Text( child: Text(
S.of(context).lightning_receive_limits( S.of(context).lightning_receive_limits(
lightning!.satsToLightningString(min), lightning!.satsToLightningString(results.minAllowedDeposit),
lightning!.satsToLightningString(max), lightning!.satsToLightningString(results.maxAllowedDeposit),
lightning!.satsToLightningString(fee), lightning!.satsToLightningString(results.fee),
), ),
maxLines: 10, maxLines: 10,
style: TextStyle( style: TextStyle(

View file

@ -11,6 +11,7 @@ import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/LightningSendViewModel.dart';
import 'package:cake_wallet/view_model/lightning_view_model.dart'; import 'package:cake_wallet/view_model/lightning_view_model.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -22,13 +23,13 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
class LightningSendConfirmPage extends BasePage { class LightningSendConfirmPage extends BasePage {
LightningSendConfirmPage({required this.invoice, required this.lightningViewModel}) LightningSendConfirmPage({required this.invoice, required this.lightningSendViewModel})
: _formKey = GlobalKey<FormState>() { : _formKey = GlobalKey<FormState>() {
initialSatAmount = ((invoice.amountMsat ?? 0) ~/ 1000); initialSatAmount = ((invoice.amountMsat ?? 0) ~/ 1000);
_amountController = TextEditingController(); _amountController = TextEditingController();
_fiatAmountController = TextEditingController(); _fiatAmountController = TextEditingController();
_amountController.text = initialSatAmount.toString(); _amountController.text = initialSatAmount.toString();
_fiatAmountController.text = lightningViewModel.formattedFiatAmount(initialSatAmount); _fiatAmountController.text = lightningSendViewModel.formattedFiatAmount(initialSatAmount);
} }
final GlobalKey<FormState> _formKey; final GlobalKey<FormState> _formKey;
@ -39,7 +40,7 @@ class LightningSendConfirmPage extends BasePage {
late TextEditingController _amountController; late TextEditingController _amountController;
late TextEditingController _fiatAmountController; late TextEditingController _fiatAmountController;
final FocusNode _depositAmountFocus = FocusNode(); final FocusNode _depositAmountFocus = FocusNode();
final LightningViewModel lightningViewModel; final LightningSendViewModel lightningSendViewModel;
bool _effectsInstalled = false; bool _effectsInstalled = false;
@ -194,7 +195,7 @@ class LightningSendConfirmPage extends BasePage {
prefixIcon: Padding( prefixIcon: Padding(
padding: EdgeInsets.only(top: 9), padding: EdgeInsets.only(top: 9),
child: Text( child: Text(
lightningViewModel.fiat.title + ':', lightningSendViewModel.fiat.title + ':',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -252,7 +253,7 @@ class LightningSendConfirmPage extends BasePage {
final sdk = await BreezSDK(); final sdk = await BreezSDK();
late BZG.SendPaymentRequest req; late BZG.SendPaymentRequest req;
lightningViewModel.setLoading(true); lightningSendViewModel.setLoading(true);
if (invoice.amountMsat == null) { if (invoice.amountMsat == null) {
req = BZG.SendPaymentRequest( req = BZG.SendPaymentRequest(
@ -265,7 +266,7 @@ class LightningSendConfirmPage extends BasePage {
await sdk.sendPayment(req: req); await sdk.sendPayment(req: req);
lightningViewModel.setLoading(false); lightningSendViewModel.setLoading(false);
showPopUp<void>( showPopUp<void>(
context: context, context: context,
@ -280,7 +281,7 @@ class LightningSendConfirmPage extends BasePage {
}); });
}); });
} catch (e) { } catch (e) {
lightningViewModel.setLoading(false); lightningSendViewModel.setLoading(false);
showPopUp<void>( showPopUp<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
@ -294,7 +295,7 @@ class LightningSendConfirmPage extends BasePage {
}, },
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
textColor: Colors.white, textColor: Colors.white,
isLoading: lightningViewModel.loading, isLoading: lightningSendViewModel.loading,
), ),
], ],
); );
@ -317,7 +318,7 @@ class LightningSendConfirmPage extends BasePage {
_amountController.addListener(() { _amountController.addListener(() {
final amount = _amountController.text; final amount = _amountController.text;
_fiatAmountController.text = lightningViewModel.formattedFiatAmount(int.parse(amount)); _fiatAmountController.text = lightningSendViewModel.formattedFiatAmount(int.parse(amount));
}); });
_effectsInstalled = true; _effectsInstalled = true;

View file

@ -11,6 +11,7 @@ import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/LightningSendViewModel.dart';
import 'package:cake_wallet/view_model/lightning_view_model.dart'; import 'package:cake_wallet/view_model/lightning_view_model.dart';
import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
@ -27,12 +28,12 @@ class LightningSendPage extends BasePage {
LightningSendPage({ LightningSendPage({
required this.output, required this.output,
required this.authService, required this.authService,
required this.lightningViewModel, required this.lightningSendViewModel,
}) : _formKey = GlobalKey<FormState>(); }) : _formKey = GlobalKey<FormState>();
final Output output; final Output output;
final AuthService authService; final AuthService authService;
final LightningViewModel lightningViewModel; final LightningSendViewModel lightningSendViewModel;
final GlobalKey<FormState> _formKey; final GlobalKey<FormState> _formKey;
final controller = PageController(initialPage: 0); final controller = PageController(initialPage: 0);

View file

@ -109,9 +109,9 @@ abstract class LightningInvoicePageViewModelBase with Store {
} }
Future<void> _fetchLimits() async { Future<void> _fetchLimits() async {
List<int> limits = await lightningViewModel.invoiceSoftLimitsSats(); final limits = await lightningViewModel.invoiceSoftLimitsSats();
minimum = limits[0].toDouble(); minimum = limits.min.toDouble();
maximum = limits[1].toDouble(); maximum = limits.max.toDouble();
} }
@action @action

View file

@ -0,0 +1,43 @@
import 'dart:async';
import 'package:breez_sdk/breez_sdk.dart';
import 'package:breez_sdk/bridge_generated.dart' as BZG;
import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/lightning/lightning.dart';
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:mobx/mobx.dart';
part 'lightning_send_view_model.g.dart';
class LightningSendViewModel = LightningSendViewModelBase with _$LightningSendViewModel;
abstract class LightningSendViewModelBase with Store {
LightningSendViewModelBase({
required this.settingsStore,
required this.fiatConversionStore,
}) {}
final SettingsStore settingsStore;
final FiatConversionStore fiatConversionStore;
@observable
bool loading = false;
@action
void setLoading(bool value) {
loading = value;
}
FiatCurrency get fiat => settingsStore.fiatCurrency;
String formattedFiatAmount(int sats) {
String amount = calculateFiatAmountRaw(
cryptoAmount: lightning!.formatterLightningAmountToDouble(amount: sats),
price: fiatConversionStore.prices[CryptoCurrency.btcln],
);
return amount;
}
}

View file

@ -14,33 +14,9 @@ part 'lightning_view_model.g.dart';
class LightningViewModel = LightningViewModelBase with _$LightningViewModel; class LightningViewModel = LightningViewModelBase with _$LightningViewModel;
abstract class LightningViewModelBase with Store { abstract class LightningViewModelBase with Store {
LightningViewModelBase({ LightningViewModelBase() {}
required this.settingsStore,
required this.fiatConversionStore,
}) {}
final SettingsStore settingsStore; Future<ReceiveOnchainResult> receiveOnchain() async {
final FiatConversionStore fiatConversionStore;
@observable
bool loading = false;
@action
void setLoading(bool value) {
loading = value;
}
FiatCurrency get fiat => settingsStore.fiatCurrency;
String formattedFiatAmount(int sats) {
String amount = calculateFiatAmountRaw(
cryptoAmount: lightning!.formatterLightningAmountToDouble(amount: sats),
price: fiatConversionStore.prices[CryptoCurrency.btcln],
);
return amount;
}
Future<List<String>> receiveOnchain() async {
final sdk = await BreezSDK(); final sdk = await BreezSDK();
BZG.ReceiveOnchainRequest req = const BZG.ReceiveOnchainRequest(); BZG.ReceiveOnchainRequest req = const BZG.ReceiveOnchainRequest();
@ -49,12 +25,12 @@ abstract class LightningViewModelBase with Store {
print("Maximum amount allowed to deposit in sats: ${swapInfo.maxAllowedDeposit}"); print("Maximum amount allowed to deposit in sats: ${swapInfo.maxAllowedDeposit}");
int fee = swapInfo.channelOpeningFees?.minMsat ?? 2000; int fee = swapInfo.channelOpeningFees?.minMsat ?? 2000;
fee = fee ~/ 1000; fee = fee ~/ 1000;
return [ return ReceiveOnchainResult(
swapInfo.bitcoinAddress, bitcoinAddress: swapInfo.bitcoinAddress,
swapInfo.minAllowedDeposit.toString(), minAllowedDeposit: swapInfo.minAllowedDeposit,
swapInfo.maxAllowedDeposit.toString(), maxAllowedDeposit: swapInfo.maxAllowedDeposit,
fee.toString(), fee: fee,
]; );
} }
Future<String> createInvoice({required String amountSats, String? description}) async { Future<String> createInvoice({required String amountSats, String? description}) async {
@ -67,7 +43,7 @@ abstract class LightningViewModelBase with Store {
return res.lnInvoice.bolt11; return res.lnInvoice.bolt11;
} }
Future<List<int>> invoiceSoftLimitsSats() async { Future<InvoiceSoftLimitsResult> invoiceSoftLimitsSats() async {
final sdk = await BreezSDK(); final sdk = await BreezSDK();
BZG.ReceivePaymentRequest? req = null; BZG.ReceivePaymentRequest? req = null;
req = BZG.ReceivePaymentRequest( req = BZG.ReceivePaymentRequest(
@ -88,7 +64,11 @@ abstract class LightningViewModelBase with Store {
min = 0; min = 0;
} }
} catch (_) {} } catch (_) {}
return [min, max, balance]; return InvoiceSoftLimitsResult(
min: min,
max: max,
balance: balance,
);
} }
Future<int> getBalanceSats() async { Future<int> getBalanceSats() async {
@ -101,3 +81,30 @@ abstract class LightningViewModelBase with Store {
} }
} }
} }
class ReceiveOnchainResult {
final String bitcoinAddress;
final int minAllowedDeposit;
final int maxAllowedDeposit;
final int fee;
ReceiveOnchainResult({
required this.bitcoinAddress,
required this.minAllowedDeposit,
required this.maxAllowedDeposit,
required this.fee,
});
}
class InvoiceSoftLimitsResult {
final int min;
final int max;
final int balance;
InvoiceSoftLimitsResult({
required this.min,
required this.max,
required this.balance,
});
}