From 506e8b7b583da36a1dc20b91f6469cebab5469b3 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Wed, 2 Apr 2025 12:27:54 -0400 Subject: [PATCH 01/14] add silent payments feature and view --- .../sub_widgets/desktop_receive.dart | 78 ++++++++- .../sub_widgets/desktop_wallet_features.dart | 9 + .../more_features/more_features_dialog.dart | 11 ++ .../silent_payments/silent_payments_view.dart | 159 ++++++++++++++++++ lib/route_generator.dart | 15 ++ pubspec.lock | 11 +- 6 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 lib/pages_desktop_specific/silent_payments/silent_payments_view.dart diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart index b90cc2f6a..a83d5326b 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart @@ -18,6 +18,8 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; +import 'package:silent_payments/silent_payments.dart'; + import '../../../../models/isar/models/isar_models.dart'; import '../../../../models/keys/view_only_wallet_data.dart'; import '../../../../notifications/show_flush_bar.dart'; @@ -198,6 +200,45 @@ class _DesktopReceiveState extends ConsumerState { } } + Future generateSilentPaymentAddress() async { + final wallet = ref.read(pWallets).getWallet(walletId); + if (wallet is BitcoinWallet) { + final rootNode = await wallet.getRootHDNode(); + final owner = SilentPaymentOwner.fromBip32(rootNode); + + // Translate the wallet's network to what the Silent Payment library expects + final network = switch (wallet.info.coin.network) { + CryptoCurrencyNetwork.main => 'BitcoinNetwork.mainnet', + CryptoCurrencyNetwork.test => 'BitcoinNetwork.testnet', + CryptoCurrencyNetwork.test4 => 'BitcoinNetwork.testnet', + _ => null + }; + + final address = Address( + walletId: walletId, + value: owner.toString(network: network), + publicKey: [], // Could store both public keys if needed + derivationIndex: 0, // Could keep track of this if generating multiple + derivationPath: null, // BIP-352 uses two paths, so this may not apply directly + type: AddressType.bip352, + subType: AddressSubType.nonWallet, + ); + + final isar = ref.read(mainDBProvider).isar; + await isar.writeTxn(() async { + await isar.addresses.put(address); + }); + + if (mounted) { + Navigator.of(context, rootNavigator: true).pop(); + + setState(() { + _addressMap[_walletAddressTypes[_currentIndex]] = address.value; + }); + } + } + } + @override void initState() { walletId = widget.walletId; @@ -231,6 +272,7 @@ class _DesktopReceiveState extends ConsumerState { if (_walletAddressTypes.length > 1 && wallet is BitcoinWallet) { _walletAddressTypes.removeWhere((e) => e == AddressType.p2pkh); + _walletAddressTypes.add(AddressType.bip352); } _addressMap[_walletAddressTypes[_currentIndex]] = @@ -238,6 +280,12 @@ class _DesktopReceiveState extends ConsumerState { if (showMultiType) { for (final type in _walletAddressTypes) { + // For Silent Payment addresses, we'll use a different approach + if (type == AddressType.bip352) { + // Check if a Silent Payment address exists + _checkAndGenerateSilentPaymentAddress(); + continue; // Skip the regular subscription for this type + } _addressSubMap[type] = ref .read(mainDBProvider) .isar @@ -265,6 +313,33 @@ class _DesktopReceiveState extends ConsumerState { super.initState(); } + // Separate method to check for and generate Silent Payment address if needed + Future _checkAndGenerateSilentPaymentAddress() async { + if (_walletAddressTypes.contains(AddressType.bip352)) { + final isar = ref.read(mainDBProvider).isar; + + // Check if a Silent Payment address already exists + final existingAddress = await isar.addresses + .where() + .walletIdEqualTo(walletId) + .filter() + .typeEqualTo(AddressType.bip352) + .findFirst(); + + if (existingAddress != null) { + // Address exists, update the map + if (mounted) { + setState(() { + _addressMap[AddressType.bip352] = existingAddress.value; + }); + } + } else { + // No address exists, generate one + await generateSilentPaymentAddress(); + } + } + } + @override void dispose() { for (final subscription in _addressSubMap.values) { @@ -290,7 +365,8 @@ class _DesktopReceiveState extends ConsumerState { final bool canGen; if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly && - wallet.viewOnlyType == ViewOnlyWalletType.addressOnly) { + wallet.viewOnlyType == ViewOnlyWalletType.addressOnly || + _walletAddressTypes[_currentIndex] == AddressType.bip352) { canGen = false; } else { canGen = (wallet is MultiAddressInterface || supportsSpark); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 78a36d8d7..6c5e58f4f 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -51,6 +51,7 @@ import '../../../desktop_menu.dart'; import '../../../lelantus_coins/lelantus_coins_view.dart'; import '../../../ordinals/desktop_ordinals_view.dart'; import '../../../spark_coins/spark_coins_view.dart'; +import '../../../silent_payments/silent_payments_view.dart'; import '../desktop_wallet_view.dart'; import 'more_features/more_features_dialog.dart'; @@ -99,6 +100,7 @@ class _DesktopWalletFeaturesState extends ConsumerState { onFusionPressed: _onFusionPressed, onChurnPressed: _onChurnPressed, onNamesPressed: _onNamesPressed, + onSilentPaymentsPressed: _onSilentPaymentsPressed, ), ); } @@ -371,6 +373,13 @@ class _DesktopWalletFeaturesState extends ConsumerState { ).pushNamed(NamecoinNamesHomeView.routeName, arguments: widget.walletId); } + void _onSilentPaymentsPressed() { + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of( + context, + ).pushNamed(SilentPaymentsView.routeName, arguments: widget.walletId); + } + @override Widget build(BuildContext context) { final wallet = ref.watch(pWallets).getWallet(widget.walletId); diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index 1ee0447b3..d39083ba3 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -32,6 +32,7 @@ import '../../../../../utilities/util.dart'; import '../../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; import '../../../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../../../wallets/wallet/impl/bitcoin_wallet.dart'; import '../../../../../wallets/wallet/impl/firo_wallet.dart'; import '../../../../../wallets/wallet/impl/namecoin_wallet.dart'; import '../../../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; @@ -67,6 +68,7 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget { required this.onFusionPressed, required this.onChurnPressed, required this.onNamesPressed, + required this.onSilentPaymentsPressed, }); final String walletId; @@ -82,6 +84,7 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget { final VoidCallback? onFusionPressed; final VoidCallback? onChurnPressed; final VoidCallback? onNamesPressed; + final VoidCallback? onSilentPaymentsPressed; @override ConsumerState createState() => _MoreFeaturesDialogState(); @@ -419,6 +422,7 @@ class _MoreFeaturesDialogState extends ConsumerState { // iconAsset: Assets.svg.whirlPool, // onPressed: () => widget.onWhirlpoolPressed?.call(), // ), + if (wallet is CoinControlInterface && coinControlPrefEnabled) _MoreFeaturesItem( label: "Coin control", @@ -457,6 +461,13 @@ class _MoreFeaturesDialogState extends ConsumerState { iconAsset: Assets.svg.robotHead, onPressed: () async => widget.onPaynymPressed?.call(), ), + if (!isViewOnly && wallet is BitcoinWallet) + _MoreFeaturesItem( + label: "Silent Payments", + detail: "Increased address privacy using BIP352", + iconAsset: Assets.svg.ellipsis, + onPressed: () async => widget.onSilentPaymentsPressed?.call(), + ), if (wallet is OrdinalsInterface) _MoreFeaturesItem( label: "Ordinals", diff --git a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart new file mode 100644 index 000000000..b05f9179e --- /dev/null +++ b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart @@ -0,0 +1,159 @@ +// ignore_for_file: unused_import, prefer_const_constructors, avoid_print + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../notifications/show_flush_bar.dart'; +import '../../themes/stack_colors.dart'; +import '../../utilities/assets.dart'; +import '../../utilities/text_styles.dart'; +import '../../utilities/util.dart'; +import '../../widgets/conditional_parent.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/desktop/desktop_app_bar.dart'; +import '../../widgets/desktop/desktop_scaffold.dart'; +import '../../widgets/desktop/secondary_button.dart'; +import '../../widgets/icon_widgets/copy_icon.dart'; +import '../../widgets/rounded_white_container.dart'; +import '../../widgets/qr.dart'; + +class SilentPaymentsView extends ConsumerStatefulWidget { + const SilentPaymentsView({super.key, required this.walletId}); + + final String walletId; + + static const String routeName = "/silentPayments"; + + @override + ConsumerState createState() => _SilentPaymentsViewState(); +} + +class _SilentPaymentsViewState extends ConsumerState { + bool _enabled = false; + bool _isLoading = false; + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + final isDesktop = Util.isDesktop; + + return MasterScaffold( + isDesktop: isDesktop, + appBar: + isDesktop + ? DesktopAppBar( + isCompactHeight: true, + background: Theme.of(context).extension()!.popupBG, + leading: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 24, right: 20), + child: AppBarIconButton( + size: 32, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + ), + onPressed: Navigator.of(context).pop, + ), + ), + Text( + "Silent Payments", + style: STextStyles.desktopH3(context), + ), + ], + ), + ) + : AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + titleSpacing: 0, + title: Text( + "Silent Payments", + style: STextStyles.navBarTitle(context), + overflow: TextOverflow.ellipsis, + ), + ), + body: + _isLoading + ? Center( + child: CircularProgressIndicator( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ) + : ConditionalParent( + condition: !isDesktop, + builder: + (child) => SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + child: Column( + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.start + : CrossAxisAlignment.center, + children: [ + ConditionalParent( + condition: isDesktop, + builder: + (child) => Padding( + padding: const EdgeInsets.all(24), + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SwitchListTile( + title: Text( + "Scan for Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.titleBold12(context), + ), + value: _enabled, + onChanged: (value) { + setState(() { + _enabled = value; + }); + }, + activeColor: + Theme.of( + context, + ).extension()!.accentColorGreen, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 6695a53b8..d6c45cf3e 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -203,6 +203,7 @@ import 'pages_desktop_specific/settings/settings_menu/security_settings.dart'; import 'pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart'; import 'pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart'; import 'pages_desktop_specific/spark_coins/spark_coins_view.dart'; +import 'pages_desktop_specific/silent_payments/silent_payments_view.dart'; import 'services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'utilities/amount/amount.dart'; @@ -2744,6 +2745,20 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case SilentPaymentsView.routeName: + if (args is String) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => SilentPaymentsView( + walletId: args, + ), + settings: RouteSettings( + name: settings.name, + ), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + // == End of desktop specific routes ===================================== default: diff --git a/pubspec.lock b/pubspec.lock index b611f6f20..fb062ebec 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1762,6 +1762,15 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + silent_payments: + dependency: "direct main" + description: + path: "." + ref: eb7324f3bcd1c82256b5cdcccaa5aa68809b9af7 + resolved-ref: eb7324f3bcd1c82256b5cdcccaa5aa68809b9af7 + url: "https://github.com/kent-3/silent_payments.git" + source: git + version: "0.1.0" sky_engine: dependency: transitive description: flutter @@ -2327,5 +2336,5 @@ packages: source: hosted version: "0.2.3" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.7.2 <4.0.0" flutter: ">=3.29.0" From 88c0fd445412bad66572e3745be3bf7e89f1c7c9 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Wed, 2 Apr 2025 12:28:55 -0400 Subject: [PATCH 02/14] update fn name in error log --- lib/wallets/wallet/wallet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wallets/wallet/wallet.dart b/lib/wallets/wallet/wallet.dart index 161c68f5f..fbab6da1a 100644 --- a/lib/wallets/wallet/wallet.dart +++ b/lib/wallets/wallet/wallet.dart @@ -564,7 +564,7 @@ abstract class Wallet { ), ); Logging.instance.e( - "Caught exception in refreshWalletData()", + "Caught exception in refresh()", error: e, stackTrace: s, ); From 9c6acff84527eaf567552912781dc16ed69c7fa7 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Wed, 9 Apr 2025 18:51:20 -0400 Subject: [PATCH 03/14] generated view layout --- .../silent_payments/silent_payments_view.dart | 846 ++++++++++++++++-- 1 file changed, 789 insertions(+), 57 deletions(-) diff --git a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart index b05f9179e..9fc52cfdd 100644 --- a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart +++ b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart @@ -1,11 +1,13 @@ // ignore_for_file: unused_import, prefer_const_constructors, avoid_print import 'dart:async'; +import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:coinlib_flutter/coinlib_flutter.dart'; import '../../notifications/show_flush_bar.dart'; import '../../themes/stack_colors.dart'; @@ -16,11 +18,14 @@ import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/desktop/desktop_app_bar.dart'; import '../../widgets/desktop/desktop_scaffold.dart'; +import '../../widgets/desktop/primary_button.dart'; import '../../widgets/desktop/secondary_button.dart'; import '../../widgets/icon_widgets/copy_icon.dart'; import '../../widgets/rounded_white_container.dart'; import '../../widgets/qr.dart'; +import 'package:silent_payments/silent_payments.dart'; + class SilentPaymentsView extends ConsumerStatefulWidget { const SilentPaymentsView({super.key, required this.walletId}); @@ -35,11 +40,307 @@ class SilentPaymentsView extends ConsumerStatefulWidget { class _SilentPaymentsViewState extends ConsumerState { bool _enabled = false; bool _isLoading = false; + bool _isGeneratingKeys = false; + + // Mock silent payment owner + SilentPaymentOwner? _owner; + String _silentPaymentAddress = ""; + String _scanPrivateKey = ""; + String _spendPrivateKey = ""; + + // Mock send fields + final TextEditingController _recipientAddressController = + TextEditingController(); + final TextEditingController _amountController = TextEditingController(); + + // Mock scanning fields + final TextEditingController _blockHeightController = TextEditingController(); + final List _detectedOutputs = []; + + // Mock debug information + final Map _debugInfo = {}; + + @override + void initState() { + super.initState(); + _blockHeightController.text = "800000"; // Example block height + _amountController.text = "0.0001"; // Example amount + } + + @override + void dispose() { + _recipientAddressController.dispose(); + _amountController.dispose(); + _blockHeightController.dispose(); + super.dispose(); + } + + // Generate or regenerate silent payment keys + Future _generateSilentPaymentKeys() async { + setState(() { + _isGeneratingKeys = true; + }); + + // In a real implementation, we would derive these from the wallet seed + // based on BIP32 derivation paths: m/352'/0'/0'/1'/0 and m/352'/0'/0'/0'/0 + + try { + // Mock implementation - in reality would derive from wallet + await Future.delayed(const Duration(milliseconds: 500)); + + // Random seed for demonstration + final seedHex = + "39c13fb2c797d1702052abede785a0370c7bc13b7834bea06bfb6b78fc4659d8"; + final seed = Uint8List.fromList(hexToBytes(seedHex)); + + // Generate keys from seed + _owner = SilentPaymentOwner.fromSeed(seed); + + _silentPaymentAddress = _owner!.toString(); + _scanPrivateKey = bytesToHex(_owner!.b_scan.data); + _spendPrivateKey = bytesToHex(_owner!.b_spend.data); + + // Update debug info + _debugInfo.clear(); + _debugInfo.addAll({ + "B_scan (Public)": bytesToHex(_owner!.address.B_scan.data), + "B_spend (Public)": bytesToHex(_owner!.address.B_spend.data), + "b_scan (Private)": _scanPrivateKey, + "b_spend (Private)": _spendPrivateKey, + }); + + setState(() { + _isGeneratingKeys = false; + }); + + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.success, + message: "Silent Payment keys generated successfully", + context: context, + ); + } + } catch (e) { + setState(() { + _isGeneratingKeys = false; + }); + + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Failed to generate Silent Payment keys: ${e.toString()}", + context: context, + ); + } + } + } + + // Mock sending silent payment + Future _sendSilentPayment() async { + final recipientAddress = _recipientAddressController.text.trim(); + final amount = _amountController.text.trim(); + + if (recipientAddress.isEmpty) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Please enter a recipient address", + context: context, + ); + return; + } + + if (amount.isEmpty || + double.tryParse(amount) == null || + double.parse(amount) <= 0) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Please enter a valid amount", + context: context, + ); + return; + } + + setState(() { + _isLoading = true; + }); + + try { + // In a real implementation, this would: + // 1. Create a transaction with inputs + // 2. Derive the shared secret + // 3. Generate output addresses + // 4. Broadcast the transaction + + await Future.delayed(const Duration(seconds: 1)); + + // Mock transaction details for demonstration + final txDetails = { + "txid": + "85a12304f5d6e14ad32b6ebe2cf39f238695c9479c55d6291c2a1fe2c4af56a3", + "outpoints": [ + "c45fc3c36d30c9b93b288e51ef59f4af6e963d8e100c752b212aeB65db2cc604:0", + "7ef3c7f4a1e247b47b1fcb075e4639955ea4c9c6674b42b8b858cbf1f738d352:1", + ], + "outputs": [ + "bc1p5gv9zay9m8w99dqeyl2p5zazg4fcw4nnfxazqpu8xre8ctmrx7aq5mhzz7", + "bc1pcqtmhrfe95e5nejx98u6kcfuxz8lnm976lmedrjxvllr4qm5t5tsl7xnw3", + ], + "amount": double.parse(amount), + "fee": 0.00001, + }; + + // Update debug info + _debugInfo.clear(); + _debugInfo.addAll({ + "Destination": recipientAddress, + "Amount": "$amount BTC", + "Transaction ID": txDetails["txid"]! as String, + "Output Addresses": (txDetails["outputs"] as List).join("\n"), + }); + + setState(() { + _isLoading = false; + }); + + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.success, + message: "Silent Payment sent successfully!", + context: context, + ); + } + } catch (e) { + setState(() { + _isLoading = false; + }); + + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Failed to send Silent Payment: ${e.toString()}", + context: context, + ); + } + } + } + + // Mock scanning for received silent payments + Future _scanForSilentPayments() async { + if (_owner == null) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Please generate Silent Payment keys first", + context: context, + ); + return; + } + + final blockHeight = _blockHeightController.text.trim(); + + if (blockHeight.isEmpty || int.tryParse(blockHeight) == null) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Please enter a valid block height", + context: context, + ); + return; + } + + setState(() { + _isLoading = true; + _detectedOutputs.clear(); + }); + + try { + // In a real implementation, this would: + // 1. Fetch block data for the given height + // 2. Extract transactions + // 3. For each transaction, calculate outpoints and input public keys + // 4. Derive shared secrets and scan outputs + + await Future.delayed(const Duration(seconds: 2)); + + // Mock detected outputs for demonstration + if (_enabled) { + _detectedOutputs.clear(); + _detectedOutputs.addAll([ + "bc1p5cyxm5c6rvfqzkjq40rrs7cnjr9qpkpz0qjmv3qr7v9dhm0rcsqsxp8hx8", + "bc1pws9t458yt9fq3ae43a9d23l0tp70yd64qme3pdhtg4rkgkut075st7qcux", + ]); + + // Update debug info + _debugInfo.clear(); + _debugInfo.addAll({ + "Block Height": blockHeight, + "Txs Scanned": "285", + "Inputs Analyzed": "843", + "Outputs Checked": "976", + "Shared Secrets": "123", + "Tagged Hashes": "432", + "Detection Method": "Shared Secret + Output Tweaking", + }); + } else { + _debugInfo.clear(); + _debugInfo.addAll({ + "Status": + "Scanning disabled - Enable scanning to detect Silent Payments", + }); + } + + setState(() { + _isLoading = false; + }); + + if (mounted) { + if (_enabled) { + await showFloatingFlushBar( + type: FlushBarType.success, + message: "Found ${_detectedOutputs.length} Silent Payment outputs", + context: context, + ); + } else { + await showFloatingFlushBar( + type: FlushBarType.info, + message: + "Scanning disabled - Enable scanning to detect Silent Payments", + context: context, + ); + } + } + } catch (e) { + setState(() { + _isLoading = false; + }); + + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: "Failed to scan for Silent Payments: ${e.toString()}", + context: context, + ); + } + } + } + + // Helper method to convert hex string to bytes + List hexToBytes(String hex) { + List bytes = []; + for (int i = 0; i < hex.length; i += 2) { + bytes.add(int.parse(hex.substring(i, i + 2), radix: 16)); + } + return bytes; + } + + // Helper method to convert bytes to hex string + String bytesToHex(List bytes) { + return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); + } @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final isDesktop = Util.isDesktop; + final isDesktop = true; // Always desktop for now + final colors = Theme.of(context).extension()!; return MasterScaffold( isDesktop: isDesktop, @@ -47,26 +348,23 @@ class _SilentPaymentsViewState extends ConsumerState { isDesktop ? DesktopAppBar( isCompactHeight: true, - background: Theme.of(context).extension()!.popupBG, + background: colors.popupBG, leading: Row( children: [ Padding( padding: const EdgeInsets.only(left: 24, right: 20), child: AppBarIconButton( size: 32, - color: - Theme.of( - context, - ).extension()!.textFieldDefaultBG, + color: colors.textFieldDefaultBG, shadows: const [], icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: - Theme.of( - context, - ).extension()!.topNavIconPrimary, + colorFilter: ColorFilter.mode( + colors.topNavIconPrimary, + BlendMode.srcIn, + ), ), onPressed: Navigator.of(context).pop, ), @@ -94,64 +392,498 @@ class _SilentPaymentsViewState extends ConsumerState { body: _isLoading ? Center( - child: CircularProgressIndicator( - color: - Theme.of( - context, - ).extension()!.accentColorDark, - ), + child: CircularProgressIndicator(color: colors.accentColorDark), ) - : ConditionalParent( - condition: !isDesktop, - builder: - (child) => SafeArea( - child: Padding( + : SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Top section: Enable scanning and generate keys + RoundedWhiteContainer( padding: const EdgeInsets.all(16), - child: child, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Row( + children: [ + Switch( + value: _enabled, + onChanged: (value) { + setState(() { + _enabled = value; + }); + }, + activeColor: colors.accentColorGreen, + ), + const SizedBox(width: 12), + Text( + "Scan for Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium( + context, + ) + : STextStyles.titleBold12( + context, + ), + ), + ], + ), + ), + SecondaryButton( + width: 170, + label: "Generate Keys", + onPressed: + _isGeneratingKeys + ? null + : _generateSilentPaymentKeys, + ), + ], + ), + if (_silentPaymentAddress.isNotEmpty) ...[ + const SizedBox(height: 16), + Text( + "Your Silent Payment Address:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _silentPaymentAddress, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + ), + ), + const SizedBox(width: 8), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.xl, + iconSpacing: 8, + icon: CopyIcon( + width: 12, + height: 12, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, + ), + onPressed: () async { + await Clipboard.setData( + ClipboardData( + text: _silentPaymentAddress, + ), + ); + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + } + }, + ), + ], + ), + const SizedBox(height: 16), + if (_silentPaymentAddress.isNotEmpty) + Center( + child: QR( + data: _silentPaymentAddress, + size: 150, + ), + ), + ], + ], + ), ), - ), - child: Column( - crossAxisAlignment: - isDesktop - ? CrossAxisAlignment.start - : CrossAxisAlignment.center, - children: [ - ConditionalParent( - condition: isDesktop, - builder: - (child) => Padding( - padding: const EdgeInsets.all(24), + + const SizedBox(height: 24), + + // Main two-column layout + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Left column: Send Silent Payment + Expanded( child: RoundedWhiteContainer( padding: const EdgeInsets.all(16), - child: child, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Send Silent Payment", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + + // Recipient address + Text( + "Recipient Address:", + style: STextStyles.desktopTextSmall( + context, + ), + ), + const SizedBox(height: 8), + TextField( + controller: _recipientAddressController, + decoration: InputDecoration( + hintText: "sp1...", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: STextStyles.desktopTextExtraSmall( + context, + ), + ), + + const SizedBox(height: 16), + + // Amount + Text( + "Amount (BTC):", + style: STextStyles.desktopTextSmall( + context, + ), + ), + const SizedBox(height: 8), + TextField( + controller: _amountController, + keyboardType: + const TextInputType.numberWithOptions( + decimal: true, + ), + decoration: InputDecoration( + hintText: "0.0001", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: STextStyles.desktopTextExtraSmall( + context, + ), + ), + + const SizedBox(height: 24), + + // Send button + Center( + child: PrimaryButton( + width: 150, + label: "Send", + onPressed: _sendSilentPayment, + ), + ), + + const SizedBox(height: 16), + + // Send process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Sending)", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Sender gets recipient's Silent Payment address (sp1...)\n" + "2. Sender collects all input public keys (A1, A2, ..., An)\n" + "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" + "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "5. Calculate sender partial secret: s = a_sum * T\n" + "6. Extract B_scan from recipient address\n" + "7. Calculate shared secret: S = B_scan * s\n" + "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "9. Generate output address: B_spend + outputTweak\n" + "10. Send payment to derived address", + style: + STextStyles.desktopTextExtraSmall( + context, + ), + ), + ), + ], + ), + ], + ), ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SwitchListTile( - title: Text( - "Scan for Silent Payments", - style: - isDesktop - ? STextStyles.desktopTextMedium(context) - : STextStyles.titleBold12(context), + + const SizedBox(width: 24), + + // Right column: Receive Silent Payment + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Received Silent Payments", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + + // Block height + Text( + "Block Height to Scan:", + style: STextStyles.desktopTextSmall( + context, + ), + ), + const SizedBox(height: 8), + TextField( + controller: _blockHeightController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "800000", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: STextStyles.desktopTextExtraSmall( + context, + ), + ), + + const SizedBox(height: 24), + + // Scan button + Center( + child: PrimaryButton( + width: 150, + label: "Scan", + onPressed: _scanForSilentPayments, + ), + ), + + const SizedBox(height: 16), + + // Detected outputs + if (_detectedOutputs.isNotEmpty) ...[ + Text( + "Detected Silent Payment Outputs:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: + _detectedOutputs.map((output) { + return Padding( + padding: + const EdgeInsets.symmetric( + vertical: 4, + ), + child: Row( + children: [ + Expanded( + child: Text( + output, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + ), + SecondaryButton( + label: "Copy", + buttonHeight: + ButtonHeight.s, + iconSpacing: 4, + icon: CopyIcon( + width: 10, + height: 10, + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonTextSecondary, + ), + onPressed: () async { + await Clipboard.setData( + ClipboardData( + text: output, + ), + ); + if (mounted) { + await showFloatingFlushBar( + type: + FlushBarType + .info, + message: + "Copied to clipboard", + iconAsset: + Assets.svg.copy, + context: context, + ); + } + }, + ), + ], + ), + ); + }).toList(), + ), + ), + ], + + const SizedBox(height: 16), + + // Receive process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Receiving)", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Recipient scans each transaction in new blocks\n" + "2. For each transaction, compute A_sum from input public keys\n" + "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "4. Calculate receiver partial secret: r = T * b_scan\n" + "5. Calculate shared secret: S = A_sum * r\n" + "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "7. Derive expected output: B_spend + outputTweak\n" + "8. Check if any transaction outputs match expected addresses\n" + "9. If match found, calculate private key: b_spend + outputTweak", + style: + STextStyles.desktopTextExtraSmall( + context, + ), + ), + ), + ], + ), + ], + ), ), - value: _enabled, - onChanged: (value) { - setState(() { - _enabled = value; - }); - }, - activeColor: - Theme.of( - context, - ).extension()!.accentColorGreen, ), ], ), - ), - ], + + const SizedBox(height: 24), + + // Debug information section + if (_debugInfo.isNotEmpty) + RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Debug Information", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _debugInfo.entries.map((entry) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + width: 150, + child: Text( + "${entry.key}:", + style: + STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + fontWeight: + FontWeight.bold, + ), + ), + ), + Expanded( + child: Text( + entry.value, + style: + STextStyles.desktopTextExtraSmall( + context, + ), + ), + ), + ], + ), + ); + }).toList(), + ), + ), + ], + ), + ), + ], + ), ), ), ); From 1a92bfe4ebe7e221a6cc0b377e1752213d308db7 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Thu, 10 Apr 2025 14:32:13 -0400 Subject: [PATCH 04/14] review layout --- .../silent_payments/silent_payments_view.dart | 1054 ++++++++--------- 1 file changed, 499 insertions(+), 555 deletions(-) diff --git a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart index 9fc52cfdd..84d4f9980 100644 --- a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart +++ b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart @@ -1,28 +1,32 @@ // ignore_for_file: unused_import, prefer_const_constructors, avoid_print import 'dart:async'; -import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:coinlib_flutter/coinlib_flutter.dart'; +import '../../../wallets/wallet/impl/bitcoin_wallet.dart'; +import '../../../providers/db/main_db_provider.dart'; +import '../../../providers/global/wallets_provider.dart'; +import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../notifications/show_flush_bar.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; +import '../../utilities/extensions/extensions.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../widgets/custom_loading_overlay.dart'; import '../../widgets/desktop/desktop_app_bar.dart'; import '../../widgets/desktop/desktop_scaffold.dart'; import '../../widgets/desktop/primary_button.dart'; import '../../widgets/desktop/secondary_button.dart'; import '../../widgets/icon_widgets/copy_icon.dart'; import '../../widgets/rounded_white_container.dart'; -import '../../widgets/qr.dart'; import 'package:silent_payments/silent_payments.dart'; @@ -39,8 +43,6 @@ class SilentPaymentsView extends ConsumerStatefulWidget { class _SilentPaymentsViewState extends ConsumerState { bool _enabled = false; - bool _isLoading = false; - bool _isGeneratingKeys = false; // Mock silent payment owner SilentPaymentOwner? _owner; @@ -65,76 +67,45 @@ class _SilentPaymentsViewState extends ConsumerState { super.initState(); _blockHeightController.text = "800000"; // Example block height _amountController.text = "0.0001"; // Example amount + _loadWalletData(); } - @override - void dispose() { - _recipientAddressController.dispose(); - _amountController.dispose(); - _blockHeightController.dispose(); - super.dispose(); - } - - // Generate or regenerate silent payment keys - Future _generateSilentPaymentKeys() async { - setState(() { - _isGeneratingKeys = true; - }); - - // In a real implementation, we would derive these from the wallet seed - // based on BIP32 derivation paths: m/352'/0'/0'/1'/0 and m/352'/0'/0'/0'/0 - - try { - // Mock implementation - in reality would derive from wallet - await Future.delayed(const Duration(milliseconds: 500)); - - // Random seed for demonstration - final seedHex = - "39c13fb2c797d1702052abede785a0370c7bc13b7834bea06bfb6b78fc4659d8"; - final seed = Uint8List.fromList(hexToBytes(seedHex)); - - // Generate keys from seed - _owner = SilentPaymentOwner.fromSeed(seed); + Future _loadWalletData() async { + final wallet = ref.read(pWallets).getWallet(widget.walletId); + if (wallet is BitcoinWallet) { + final rootNode = await wallet.getRootHDNode(); + final owner = SilentPaymentOwner.fromBip32(rootNode); + + // Translate the wallet's network to what the Silent Payment library expects + final network = switch (wallet.info.coin.network) { + CryptoCurrencyNetwork.main => 'BitcoinNetwork.mainnet', + CryptoCurrencyNetwork.test => 'BitcoinNetwork.testnet', + CryptoCurrencyNetwork.test4 => 'BitcoinNetwork.testnet', + _ => null, + }; - _silentPaymentAddress = _owner!.toString(); - _scanPrivateKey = bytesToHex(_owner!.b_scan.data); - _spendPrivateKey = bytesToHex(_owner!.b_spend.data); + _owner = owner; + _silentPaymentAddress = owner.toString(network: network); + _scanPrivateKey = owner.b_scan.data.toHex; + _spendPrivateKey = owner.b_spend.data.toHex; // Update debug info _debugInfo.clear(); _debugInfo.addAll({ - "B_scan (Public)": bytesToHex(_owner!.address.B_scan.data), - "B_spend (Public)": bytesToHex(_owner!.address.B_spend.data), - "b_scan (Private)": _scanPrivateKey, - "b_spend (Private)": _spendPrivateKey, + "b_scan": _scanPrivateKey, + "b_spend": _spendPrivateKey, }); - - setState(() { - _isGeneratingKeys = false; - }); - - if (mounted) { - await showFloatingFlushBar( - type: FlushBarType.success, - message: "Silent Payment keys generated successfully", - context: context, - ); - } - } catch (e) { - setState(() { - _isGeneratingKeys = false; - }); - - if (mounted) { - await showFloatingFlushBar( - type: FlushBarType.warning, - message: "Failed to generate Silent Payment keys: ${e.toString()}", - context: context, - ); - } } } + @override + void dispose() { + _recipientAddressController.dispose(); + _amountController.dispose(); + _blockHeightController.dispose(); + super.dispose(); + } + // Mock sending silent payment Future _sendSilentPayment() async { final recipientAddress = _recipientAddressController.text.trim(); @@ -160,9 +131,26 @@ class _SilentPaymentsViewState extends ConsumerState { return; } - setState(() { - _isLoading = true; - }); + bool shouldPop = false; + unawaited( + showDialog( + context: context, + builder: (_) { + return WillPopScope( + onWillPop: () async => shouldPop, + child: Container( + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), + child: const CustomLoadingOverlay( + message: "Sending Silent Payment", + eventBus: null, + ), + ), + ); + }, + ), + ); try { // In a real implementation, this would: @@ -198,10 +186,6 @@ class _SilentPaymentsViewState extends ConsumerState { "Output Addresses": (txDetails["outputs"] as List).join("\n"), }); - setState(() { - _isLoading = false; - }); - if (mounted) { await showFloatingFlushBar( type: FlushBarType.success, @@ -210,10 +194,6 @@ class _SilentPaymentsViewState extends ConsumerState { ); } } catch (e) { - setState(() { - _isLoading = false; - }); - if (mounted) { await showFloatingFlushBar( type: FlushBarType.warning, @@ -222,6 +202,15 @@ class _SilentPaymentsViewState extends ConsumerState { ); } } + + shouldPop = true; + + if (mounted) { + Navigator.of(context, rootNavigator: true).pop(); + // setState(() { + // _isLoading = false; + // }); + } } // Mock scanning for received silent payments @@ -247,10 +236,30 @@ class _SilentPaymentsViewState extends ConsumerState { } setState(() { - _isLoading = true; _detectedOutputs.clear(); }); + bool shouldPop = false; + unawaited( + showDialog( + context: context, + builder: (_) { + return WillPopScope( + onWillPop: () async => shouldPop, + child: Container( + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), + child: const CustomLoadingOverlay( + message: "Scanning...", + eventBus: null, + ), + ), + ); + }, + ), + ); + try { // In a real implementation, this would: // 1. Fetch block data for the given height @@ -276,8 +285,6 @@ class _SilentPaymentsViewState extends ConsumerState { "Inputs Analyzed": "843", "Outputs Checked": "976", "Shared Secrets": "123", - "Tagged Hashes": "432", - "Detection Method": "Shared Secret + Output Tweaking", }); } else { _debugInfo.clear(); @@ -287,10 +294,6 @@ class _SilentPaymentsViewState extends ConsumerState { }); } - setState(() { - _isLoading = false; - }); - if (mounted) { if (_enabled) { await showFloatingFlushBar( @@ -308,10 +311,6 @@ class _SilentPaymentsViewState extends ConsumerState { } } } catch (e) { - setState(() { - _isLoading = false; - }); - if (mounted) { await showFloatingFlushBar( type: FlushBarType.warning, @@ -320,26 +319,21 @@ class _SilentPaymentsViewState extends ConsumerState { ); } } - } - // Helper method to convert hex string to bytes - List hexToBytes(String hex) { - List bytes = []; - for (int i = 0; i < hex.length; i += 2) { - bytes.add(int.parse(hex.substring(i, i + 2), radix: 16)); - } - return bytes; - } + shouldPop = true; - // Helper method to convert bytes to hex string - String bytesToHex(List bytes) { - return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); + if (mounted) { + Navigator.of(context, rootNavigator: true).pop(); + // setState(() { + // _isLoading = false; + // }); + } } @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final isDesktop = true; // Always desktop for now + final isDesktop = Util.isDesktop; final colors = Theme.of(context).extension()!; return MasterScaffold( @@ -389,418 +383,434 @@ class _SilentPaymentsViewState extends ConsumerState { overflow: TextOverflow.ellipsis, ), ), - body: - _isLoading - ? Center( - child: CircularProgressIndicator(color: colors.accentColorDark), - ) - : SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top section: Enable scanning and generate keys - RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Row( - children: [ - Switch( - value: _enabled, - onChanged: (value) { - setState(() { - _enabled = value; - }); - }, - activeColor: colors.accentColorGreen, - ), - const SizedBox(width: 12), - Text( - "Scan for Silent Payments", - style: - isDesktop - ? STextStyles.desktopTextMedium( - context, - ) - : STextStyles.titleBold12( - context, - ), - ), - ], - ), - ), - SecondaryButton( - width: 170, - label: "Generate Keys", - onPressed: - _isGeneratingKeys - ? null - : _generateSilentPaymentKeys, - ), - ], - ), - if (_silentPaymentAddress.isNotEmpty) ...[ - const SizedBox(height: 16), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Top section: Enable scanning and generate keys + RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Row( + children: [ + Switch( + value: _enabled, + onChanged: (value) { + setState(() { + _enabled = value; + }); + }, + activeColor: colors.accentColorGreen, + ), + const SizedBox(width: 12), Text( - "Your Silent Payment Address:", - style: STextStyles.desktopTextSmall( + "Scan for Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.titleBold12(context), + ), + ], + ), + ), + ], + ), + if (_silentPaymentAddress.isNotEmpty) ...[ + const SizedBox(height: 16), + Text( + "Your Silent Payment Address:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _silentPaymentAddress, + style: STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith(fontWeight: FontWeight.bold), + ), ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Text( - _silentPaymentAddress, - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), - ), - ), - const SizedBox(width: 8), - SecondaryButton( - label: "Copy", - buttonHeight: ButtonHeight.xl, - iconSpacing: 8, - icon: CopyIcon( - width: 12, - height: 12, - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - onPressed: () async { - await Clipboard.setData( - ClipboardData( - text: _silentPaymentAddress, - ), - ); - if (mounted) { - await showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - } - }, - ), - ], + ), + ), + const SizedBox(width: 8), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.m, + iconSpacing: 8, + icon: CopyIcon( + width: 12, + height: 12, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, + ), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: _silentPaymentAddress), + ); + if (context.mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + } + }, + ), + ], + ), + ], + ], + ), + ), + + const SizedBox(height: 24), + + // Main two-column layout + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Left column: Send Silent Payment + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Send Silent Payment", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + + // Recipient address + Text( + "Recipient Address:", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 8), + TextField( + controller: _recipientAddressController, + decoration: InputDecoration( + hintText: "sp1...", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, ), - const SizedBox(height: 16), - if (_silentPaymentAddress.isNotEmpty) - Center( - child: QR( - data: _silentPaymentAddress, - size: 150, + ), + style: STextStyles.desktopTextExtraSmall(context), + minLines: 3, + maxLines: 3, + ), + + const SizedBox(height: 16), + + // Amount + Text( + "Amount (BTC):", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 8), + TextField( + controller: _amountController, + keyboardType: const TextInputType.numberWithOptions( + decimal: true, + ), + decoration: InputDecoration( + hintText: "0.0001", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: STextStyles.desktopTextExtraSmall(context), + ), + + const SizedBox(height: 24), + + // Send button + Center( + child: PrimaryButton( + width: 150, + label: "Send", + onPressed: _sendSilentPayment, + ), + ), + + const SizedBox(height: 16), + + // Send process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Sending)", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Sender gets recipient's Silent Payment address (sp1...)\n" + "2. Sender collects all input public keys (A1, A2, ..., An)\n" + "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" + "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "5. Calculate sender partial secret: s = a_sum * T\n" + "6. Extract B_scan from recipient address\n" + "7. Calculate shared secret: S = B_scan * s\n" + "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "9. Generate output address: B_spend + outputTweak\n" + "10. Send payment to derived address", + style: STextStyles.desktopTextExtraSmall( + context, ), ), + ), ], - ], - ), + ), + ], ), + ), + ), - const SizedBox(height: 24), + const SizedBox(width: 24), - // Main two-column layout - Row( + // Right column: Receive Silent Payment + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Left column: Send Silent Payment - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Send Silent Payment", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - - // Recipient address - Text( - "Recipient Address:", - style: STextStyles.desktopTextSmall( - context, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _recipientAddressController, - decoration: InputDecoration( - hintText: "sp1...", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - ), - style: STextStyles.desktopTextExtraSmall( - context, - ), - ), - - const SizedBox(height: 16), + Text( + "Scan for Received Silent Payments", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), - // Amount - Text( - "Amount (BTC):", - style: STextStyles.desktopTextSmall( - context, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _amountController, - keyboardType: - const TextInputType.numberWithOptions( - decimal: true, - ), - decoration: InputDecoration( - hintText: "0.0001", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - ), - style: STextStyles.desktopTextExtraSmall( - context, - ), - ), + // Block height + Text( + "Block Height to Scan:", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 8), + TextField( + controller: _blockHeightController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "800000", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: STextStyles.desktopTextExtraSmall(context), + ), - const SizedBox(height: 24), + const SizedBox(height: 24), - // Send button - Center( - child: PrimaryButton( - width: 150, - label: "Send", - onPressed: _sendSilentPayment, - ), - ), + // Scan button + Center( + child: PrimaryButton( + width: 150, + label: "Scan", + onPressed: _scanForSilentPayments, + ), + ), - const SizedBox(height: 16), + const SizedBox(height: 16), - // Send process explanation - ExpansionTile( - title: Text( - "How Silent Payments Work (Sending)", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text( - "1. Sender gets recipient's Silent Payment address (sp1...)\n" - "2. Sender collects all input public keys (A1, A2, ..., An)\n" - "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" - "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" - "5. Calculate sender partial secret: s = a_sum * T\n" - "6. Extract B_scan from recipient address\n" - "7. Calculate shared secret: S = B_scan * s\n" - "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" - "9. Generate output address: B_spend + outputTweak\n" - "10. Send payment to derived address", - style: - STextStyles.desktopTextExtraSmall( - context, + // Detected outputs + if (_detectedOutputs.isNotEmpty) ...[ + Text( + "Detected Silent Payment Outputs:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _detectedOutputs.map((output) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, + ), + child: Row( + children: [ + Expanded( + child: Text( + output, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + ), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.s, + iconSpacing: 4, + icon: CopyIcon( + width: 10, + height: 10, + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonTextSecondary, ), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: output), + ); + if (context.mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + } + }, + ), + ], ), - ), - ], - ), - ], + ); + }).toList(), ), ), - ), + ], - const SizedBox(width: 24), + const SizedBox(height: 16), - // Right column: Receive Silent Payment - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Received Silent Payments", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - - // Block height - Text( - "Block Height to Scan:", - style: STextStyles.desktopTextSmall( - context, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _blockHeightController, - keyboardType: TextInputType.number, - decoration: InputDecoration( - hintText: "800000", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - ), - style: STextStyles.desktopTextExtraSmall( - context, - ), + // Receive process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Receiving)", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Recipient scans each transaction in new blocks\n" + "2. For each transaction, compute A_sum from input public keys\n" + "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "4. Calculate receiver partial secret: r = T * b_scan\n" + "5. Calculate shared secret: S = A_sum * r\n" + "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "7. Derive expected output: B_spend + outputTweak\n" + "8. Check if any transaction outputs match expected addresses\n" + "9. If match found, calculate private key: b_spend + outputTweak", + style: STextStyles.desktopTextExtraSmall( + context, ), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), - const SizedBox(height: 24), + const SizedBox(height: 24), - // Scan button - Center( - child: PrimaryButton( - width: 150, - label: "Scan", - onPressed: _scanForSilentPayments, - ), + // Debug information section + if (_debugInfo.isNotEmpty) + RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Debug Information", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _debugInfo.entries.map((entry) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, ), - - const SizedBox(height: 16), - - // Detected outputs - if (_detectedOutputs.isNotEmpty) ...[ - Text( - "Detected Silent Payment Outputs:", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: - _detectedOutputs.map((output) { - return Padding( - padding: - const EdgeInsets.symmetric( - vertical: 4, - ), - child: Row( - children: [ - Expanded( - child: Text( - output, - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), - ), - SecondaryButton( - label: "Copy", - buttonHeight: - ButtonHeight.s, - iconSpacing: 4, - icon: CopyIcon( - width: 10, - height: 10, - color: - Theme.of(context) - .extension< - StackColors - >()! - .buttonTextSecondary, - ), - onPressed: () async { - await Clipboard.setData( - ClipboardData( - text: output, - ), - ); - if (mounted) { - await showFloatingFlushBar( - type: - FlushBarType - .info, - message: - "Copied to clipboard", - iconAsset: - Assets.svg.copy, - context: context, - ); - } - }, - ), - ], - ), - ); - }).toList(), - ), - ), - ], - - const SizedBox(height: 16), - - // Receive process explanation - ExpansionTile( - title: Text( - "How Silent Payments Work (Receiving)", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Padding( - padding: const EdgeInsets.all(16), + SizedBox( + width: 150, child: Text( - "1. Recipient scans each transaction in new blocks\n" - "2. For each transaction, compute A_sum from input public keys\n" - "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" - "4. Calculate receiver partial secret: r = T * b_scan\n" - "5. Calculate shared secret: S = A_sum * r\n" - "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" - "7. Derive expected output: B_spend + outputTweak\n" - "8. Check if any transaction outputs match expected addresses\n" - "9. If match found, calculate private key: b_spend + outputTweak", + "${entry.key}:", + style: + STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: Text( + entry.value, style: STextStyles.desktopTextExtraSmall( context, @@ -809,83 +819,17 @@ class _SilentPaymentsViewState extends ConsumerState { ), ], ), - ], - ), - ), - ), - ], - ), - - const SizedBox(height: 24), - - // Debug information section - if (_debugInfo.isNotEmpty) - RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Debug Information", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: - _debugInfo.entries.map((entry) { - return Padding( - padding: const EdgeInsets.symmetric( - vertical: 4, - ), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 150, - child: Text( - "${entry.key}:", - style: - STextStyles.desktopTextExtraSmall( - context, - ).copyWith( - fontWeight: - FontWeight.bold, - ), - ), - ), - Expanded( - child: Text( - entry.value, - style: - STextStyles.desktopTextExtraSmall( - context, - ), - ), - ), - ], - ), - ); - }).toList(), - ), - ), - ], - ), + ); + }).toList(), ), + ), ], ), ), - ), + ], + ), + ), + ), ); } } From dfbdb3a24b5649e307687033c5a80d77dde72d81 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Thu, 10 Apr 2025 20:19:49 -0400 Subject: [PATCH 05/14] change to ConfitionalParent --- .../silent_payments/silent_payments_view.dart | 777 +++++++++--------- 1 file changed, 388 insertions(+), 389 deletions(-) diff --git a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart index 84d4f9980..67d7050c3 100644 --- a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart +++ b/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart @@ -383,451 +383,450 @@ class _SilentPaymentsViewState extends ConsumerState { overflow: TextOverflow.ellipsis, ), ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top section: Enable scanning and generate keys - RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + body: ConditionalParent( + condition: !isDesktop, + builder: + (child) => SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), + ), + child: Column( + crossAxisAlignment: + isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Row( + children: [ + Switch( + value: _enabled, + onChanged: (value) { + setState(() { + _enabled = value; + }); + }, + activeColor: colors.accentColorGreen, + ), + const SizedBox(width: 12), + Text( + "Scan for Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.titleBold12(context), + ), + ], + ), + ), + ], + ), + if (_silentPaymentAddress.isNotEmpty) ...[ + const SizedBox(height: 16), + Text( + "Your Silent Payment Address:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( - child: Row( - children: [ - Switch( - value: _enabled, - onChanged: (value) { - setState(() { - _enabled = value; - }); - }, - activeColor: colors.accentColorGreen, - ), - const SizedBox(width: 12), - Text( - "Scan for Silent Payments", - style: - isDesktop - ? STextStyles.desktopTextMedium(context) - : STextStyles.titleBold12(context), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _silentPaymentAddress, + style: STextStyles.desktopTextExtraExtraSmall( + context, ), - ], + ), ), ), - ], - ), - if (_silentPaymentAddress.isNotEmpty) ...[ - const SizedBox(height: 16), - Text( - "Your Silent Payment Address:", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Text( - _silentPaymentAddress, - style: STextStyles.desktopTextExtraExtraSmall( + const SizedBox(width: 8), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.m, + iconSpacing: 8, + icon: CopyIcon( + width: 12, + height: 12, + color: + Theme.of( context, - ), - ), - ), + ).extension()!.buttonTextSecondary, ), - const SizedBox(width: 8), - SecondaryButton( - label: "Copy", - buttonHeight: ButtonHeight.m, - iconSpacing: 8, - icon: CopyIcon( - width: 12, - height: 12, - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - onPressed: () async { - await Clipboard.setData( - ClipboardData(text: _silentPaymentAddress), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: _silentPaymentAddress), + ); + if (context.mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, ); - if (context.mounted) { - await showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - } - }, - ), - ], - ), - ], + } + }, + ), + ], + ), ], - ), + ], ), + ), - const SizedBox(height: 24), - - // Main two-column layout - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Left column: Send Silent Payment - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Send Silent Payment", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), + const SizedBox(height: 24), + + // Main two-column layout + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Left column: Send Silent Payment + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Send Silent Payment", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), - // Recipient address - Text( - "Recipient Address:", - style: STextStyles.desktopTextSmall(context), - ), - const SizedBox(height: 8), - TextField( - controller: _recipientAddressController, - decoration: InputDecoration( - hintText: "sp1...", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), + // Recipient address + Text( + "Recipient Address:", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 8), + TextField( + controller: _recipientAddressController, + decoration: InputDecoration( + hintText: "sp1...", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, ), - style: STextStyles.desktopTextExtraSmall(context), - minLines: 3, - maxLines: 3, ), + style: STextStyles.desktopTextExtraSmall(context), + minLines: 3, + maxLines: 3, + ), - const SizedBox(height: 16), + const SizedBox(height: 16), - // Amount - Text( - "Amount (BTC):", - style: STextStyles.desktopTextSmall(context), + // Amount + Text( + "Amount (BTC):", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 8), + TextField( + controller: _amountController, + keyboardType: const TextInputType.numberWithOptions( + decimal: true, ), - const SizedBox(height: 8), - TextField( - controller: _amountController, - keyboardType: const TextInputType.numberWithOptions( - decimal: true, - ), - decoration: InputDecoration( - hintText: "0.0001", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), + decoration: InputDecoration( + hintText: "0.0001", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, ), - style: STextStyles.desktopTextExtraSmall(context), ), + style: STextStyles.desktopTextExtraSmall(context), + ), - const SizedBox(height: 24), + const SizedBox(height: 24), - // Send button - Center( - child: PrimaryButton( - width: 150, - label: "Send", - onPressed: _sendSilentPayment, - ), + // Send button + Center( + child: PrimaryButton( + width: 150, + label: "Send", + onPressed: _sendSilentPayment, ), + ), - const SizedBox(height: 16), + const SizedBox(height: 16), - // Send process explanation - ExpansionTile( - title: Text( - "How Silent Payments Work (Sending)", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text( - "1. Sender gets recipient's Silent Payment address (sp1...)\n" - "2. Sender collects all input public keys (A1, A2, ..., An)\n" - "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" - "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" - "5. Calculate sender partial secret: s = a_sum * T\n" - "6. Extract B_scan from recipient address\n" - "7. Calculate shared secret: S = B_scan * s\n" - "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" - "9. Generate output address: B_spend + outputTweak\n" - "10. Send payment to derived address", - style: STextStyles.desktopTextExtraSmall( - context, - ), + // Send process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Sending)", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Sender gets recipient's Silent Payment address (sp1...)\n" + "2. Sender collects all input public keys (A1, A2, ..., An)\n" + "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" + "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "5. Calculate sender partial secret: s = a_sum * T\n" + "6. Extract B_scan from recipient address\n" + "7. Calculate shared secret: S = B_scan * s\n" + "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "9. Generate output address: B_spend + outputTweak\n" + "10. Send payment to derived address", + style: STextStyles.desktopTextExtraSmall( + context, ), ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), + ), - const SizedBox(width: 24), + const SizedBox(width: 24), - // Right column: Receive Silent Payment - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Received Silent Payments", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), + // Right column: Receive Silent Payment + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Received Silent Payments", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), - // Block height - Text( - "Block Height to Scan:", - style: STextStyles.desktopTextSmall(context), - ), - const SizedBox(height: 8), - TextField( - controller: _blockHeightController, - keyboardType: TextInputType.number, - decoration: InputDecoration( - hintText: "800000", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), + // Block height + Text( + "Block Height to Scan:", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 8), + TextField( + controller: _blockHeightController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "800000", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, ), - style: STextStyles.desktopTextExtraSmall(context), ), + style: STextStyles.desktopTextExtraSmall(context), + ), - const SizedBox(height: 24), + const SizedBox(height: 24), - // Scan button - Center( - child: PrimaryButton( - width: 150, - label: "Scan", - onPressed: _scanForSilentPayments, - ), + // Scan button + Center( + child: PrimaryButton( + width: 150, + label: "Scan", + onPressed: _scanForSilentPayments, ), + ), - const SizedBox(height: 16), + const SizedBox(height: 16), - // Detected outputs - if (_detectedOutputs.isNotEmpty) ...[ - Text( - "Detected Silent Payment Outputs:", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), + // Detected outputs + if (_detectedOutputs.isNotEmpty) ...[ + Text( + "Detected Silent Payment Outputs:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: - _detectedOutputs.map((output) { - return Padding( - padding: const EdgeInsets.symmetric( - vertical: 4, - ), - child: Row( - children: [ - Expanded( - child: Text( - output, - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _detectedOutputs.map((output) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, + ), + child: Row( + children: [ + Expanded( + child: Text( + output, + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), - SecondaryButton( - label: "Copy", - buttonHeight: ButtonHeight.s, - iconSpacing: 4, - icon: CopyIcon( - width: 10, - height: 10, - color: - Theme.of(context) - .extension< - StackColors - >()! - .buttonTextSecondary, - ), - onPressed: () async { - await Clipboard.setData( - ClipboardData(text: output), - ); - if (context.mounted) { - await showFloatingFlushBar( - type: FlushBarType.info, - message: - "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - } - }, + ), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.s, + iconSpacing: 4, + icon: CopyIcon( + width: 10, + height: 10, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), - ], - ), - ); - }).toList(), - ), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: output), + ); + if (context.mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + } + }, + ), + ], + ), + ); + }).toList(), ), - ], + ), + ], - const SizedBox(height: 16), + const SizedBox(height: 16), - // Receive process explanation - ExpansionTile( - title: Text( - "How Silent Payments Work (Receiving)", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text( - "1. Recipient scans each transaction in new blocks\n" - "2. For each transaction, compute A_sum from input public keys\n" - "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" - "4. Calculate receiver partial secret: r = T * b_scan\n" - "5. Calculate shared secret: S = A_sum * r\n" - "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" - "7. Derive expected output: B_spend + outputTweak\n" - "8. Check if any transaction outputs match expected addresses\n" - "9. If match found, calculate private key: b_spend + outputTweak", - style: STextStyles.desktopTextExtraSmall( - context, - ), + // Receive process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Receiving)", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Recipient scans each transaction in new blocks\n" + "2. For each transaction, compute A_sum from input public keys\n" + "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "4. Calculate receiver partial secret: r = T * b_scan\n" + "5. Calculate shared secret: S = A_sum * r\n" + "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "7. Derive expected output: B_spend + outputTweak\n" + "8. Check if any transaction outputs match expected addresses\n" + "9. If match found, calculate private key: b_spend + outputTweak", + style: STextStyles.desktopTextExtraSmall( + context, ), ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), - ], - ), + ), + ], + ), - const SizedBox(height: 24), + const SizedBox(height: 24), - // Debug information section - if (_debugInfo.isNotEmpty) - RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Debug Information", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), + // Debug information section + if (_debugInfo.isNotEmpty) + RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Debug Information", + style: STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), ), - const SizedBox(height: 16), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: - _debugInfo.entries.map((entry) { - return Padding( - padding: const EdgeInsets.symmetric( - vertical: 4, - ), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 150, - child: Text( - "${entry.key}:", - style: - STextStyles.desktopTextExtraSmall( - context, - ).copyWith( - fontWeight: FontWeight.bold, - ), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _debugInfo.entries.map((entry) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 150, + child: Text( + "${entry.key}:", + style: + STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + fontWeight: FontWeight.bold, + ), ), - Expanded( - child: Text( - entry.value, - style: - STextStyles.desktopTextExtraSmall( - context, - ), - ), + ), + Expanded( + child: Text( + entry.value, + style: + STextStyles.desktopTextExtraSmall( + context, + ), ), - ], - ), - ); - }).toList(), - ), + ), + ], + ), + ); + }).toList(), ), - ], - ), + ), + ], ), - ], - ), + ), + ], ), ), ); From fe27999b09918b9291f04a31c9f877a2e14d149d Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Thu, 10 Apr 2025 23:35:14 -0400 Subject: [PATCH 06/14] move into regular pages directory --- .../silent_payments/silent_payments_view.dart | 182 +- .../sub_widgets/desktop_wallet_features.dart | 2 +- lib/route_generator.dart | 1640 +++++++---------- 3 files changed, 721 insertions(+), 1103 deletions(-) rename lib/{pages_desktop_specific => pages}/silent_payments/silent_payments_view.dart (86%) diff --git a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart b/lib/pages/silent_payments/silent_payments_view.dart similarity index 86% rename from lib/pages_desktop_specific/silent_payments/silent_payments_view.dart rename to lib/pages/silent_payments/silent_payments_view.dart index 67d7050c3..d0f00dcc7 100644 --- a/lib/pages_desktop_specific/silent_payments/silent_payments_view.dart +++ b/lib/pages/silent_payments/silent_payments_view.dart @@ -393,104 +393,110 @@ class _SilentPaymentsViewState extends ConsumerState { crossAxisAlignment: isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + if (isDesktop) + Padding( + padding: const EdgeInsets.all(24), + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Row( - children: [ - Switch( - value: _enabled, - onChanged: (value) { - setState(() { - _enabled = value; - }); - }, - activeColor: colors.accentColorGreen, - ), - const SizedBox(width: 12), - Text( - "Scan for Silent Payments", - style: - isDesktop - ? STextStyles.desktopTextMedium(context) - : STextStyles.titleBold12(context), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Row( + children: [ + Switch( + value: _enabled, + onChanged: (value) { + setState(() { + _enabled = value; + }); + }, + activeColor: colors.accentColorGreen, + ), + const SizedBox(width: 12), + Text( + "Scan for Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium( + context, + ) + : STextStyles.titleBold12(context), + ), + ], ), - ], - ), + ), + ], ), - ], - ), - if (_silentPaymentAddress.isNotEmpty) ...[ - const SizedBox(height: 16), - Text( - "Your Silent Payment Address:", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), + if (_silentPaymentAddress.isNotEmpty) ...[ + const SizedBox(height: 16), + Text( + "Your Silent Payment Address:", + style: STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _silentPaymentAddress, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + ), ), - child: Text( - _silentPaymentAddress, - style: STextStyles.desktopTextExtraExtraSmall( - context, + const SizedBox(width: 8), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.m, + iconSpacing: 8, + icon: CopyIcon( + width: 12, + height: 12, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: _silentPaymentAddress), + ); + if (context.mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + } + }, ), - ), - ), - const SizedBox(width: 8), - SecondaryButton( - label: "Copy", - buttonHeight: ButtonHeight.m, - iconSpacing: 8, - icon: CopyIcon( - width: 12, - height: 12, - color: - Theme.of( - context, - ).extension()!.buttonTextSecondary, - ), - onPressed: () async { - await Clipboard.setData( - ClipboardData(text: _silentPaymentAddress), - ); - if (context.mounted) { - await showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - } - }, + ], ), ], - ), - ], - ], + ], + ), + ), ), - ), - const SizedBox(height: 24), + if (!isDesktop) const SizedBox(height: 24), // Main two-column layout Row( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart index 6c5e58f4f..2c1c51536 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -21,6 +21,7 @@ import '../../../../pages/monkey/monkey_view.dart'; import '../../../../pages/namecoin_names/namecoin_names_home_view.dart'; import '../../../../pages/paynym/paynym_claim_view.dart'; import '../../../../pages/paynym/paynym_home_view.dart'; +import '../../../../pages/silent_payments/silent_payments_view.dart'; import '../../../../providers/desktop/current_desktop_menu_item.dart'; import '../../../../providers/global/paynym_api_provider.dart'; import '../../../../providers/providers.dart'; @@ -51,7 +52,6 @@ import '../../../desktop_menu.dart'; import '../../../lelantus_coins/lelantus_coins_view.dart'; import '../../../ordinals/desktop_ordinals_view.dart'; import '../../../spark_coins/spark_coins_view.dart'; -import '../../../silent_payments/silent_payments_view.dart'; import '../desktop_wallet_view.dart'; import 'more_features/more_features_dialog.dart'; diff --git a/lib/route_generator.dart b/lib/route_generator.dart index d6c45cf3e..49fdeddf1 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -147,6 +147,7 @@ import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_setting import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart'; import 'pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart'; +import 'pages/silent_payments/silent_payments_view.dart'; import 'pages/special/firo_rescan_recovery_error_dialog.dart'; import 'pages/stack_privacy_calls.dart'; import 'pages/token_view/my_tokens_view.dart'; @@ -203,7 +204,6 @@ import 'pages_desktop_specific/settings/settings_menu/security_settings.dart'; import 'pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart'; import 'pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart'; import 'pages_desktop_specific/spark_coins/spark_coins_view.dart'; -import 'pages_desktop_specific/silent_payments/silent_payments_view.dart'; import 'services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'utilities/amount/amount.dart'; @@ -254,12 +254,8 @@ class RouteGenerator { if (args is bool) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreatePinView( - popOnSuccess: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CreatePinView(popOnSuccess: args), + settings: RouteSettings(name: settings.name), ); } return getRoute( @@ -286,14 +282,13 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChooseCoinView( - title: args.item1, - coinAdditional: args.item2, - nextRouteName: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ChooseCoinView( + title: args.item1, + coinAdditional: args.item2, + nextRouteName: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -302,12 +297,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ManageExplorerView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ManageExplorerView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -316,12 +307,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FiroRescanRecoveryErrorView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FiroRescanRecoveryErrorView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -344,23 +331,18 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditWalletTokensView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditWalletTokensView(walletId: args), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple2>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditWalletTokensView( - walletId: args.item1, - contractsToMarkSelected: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditWalletTokensView( + walletId: args.item1, + contractsToMarkSelected: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -369,12 +351,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopTokenView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopTokenView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -383,12 +361,8 @@ class RouteGenerator { if (args is EthTokenEntity) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SelectWalletForTokenView( - entity: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SelectWalletForTokenView(entity: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -397,21 +371,15 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => const AddCustomTokenView(), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); case WalletsOverview.routeName: if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletsOverview( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletsOverview(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -420,13 +388,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenContractDetailsView( - contractAddress: args.item1, - walletId: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TokenContractDetailsView( + contractAddress: args.item1, + walletId: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -435,13 +402,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SingleFieldEditView( - initialValue: args.item1, - label: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SingleFieldEditView( + initialValue: args.item1, + label: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -450,66 +416,50 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => MonkeyView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => MonkeyView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case CreateNewFrostMsWalletView.routeName: - if (args is ({ - String walletName, - FrostCurrency frostCurrency, - })) { + if (args is ({String walletName, FrostCurrency frostCurrency})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreateNewFrostMsWalletView( - walletName: args.walletName, - frostCurrency: args.frostCurrency, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CreateNewFrostMsWalletView( + walletName: args.walletName, + frostCurrency: args.frostCurrency, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreFrostMsWalletView.routeName: - if (args is ({ - String walletName, - FrostCurrency frostCurrency, - })) { + if (args is ({String walletName, FrostCurrency frostCurrency})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreFrostMsWalletView( - walletName: args.walletName, - frostCurrency: args.frostCurrency, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreFrostMsWalletView( + walletName: args.walletName, + frostCurrency: args.frostCurrency, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case SelectNewFrostImportTypeView.routeName: - if (args is ({ - String walletName, - FrostCurrency frostCurrency, - })) { + if (args is ({String walletName, FrostCurrency frostCurrency})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SelectNewFrostImportTypeView( - walletName: args.walletName, - frostCurrency: args.frostCurrency, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SelectNewFrostImportTypeView( + walletName: args.walletName, + frostCurrency: args.frostCurrency, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -518,21 +468,15 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => const FrostStepScaffold(), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); case FrostMSWalletOptionsView.routeName: if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FrostMSWalletOptionsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FrostMSWalletOptionsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -541,12 +485,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FrostParticipantsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FrostParticipantsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -555,12 +495,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => InitiateResharingView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => InitiateResharingView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -569,31 +505,23 @@ class RouteGenerator { if (args is ({String walletId, Map resharers})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CompleteReshareConfigView( - walletId: args.walletId, - resharers: args.resharers, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CompleteReshareConfigView( + walletId: args.walletId, + resharers: args.resharers, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case FrostSendView.routeName: - if (args is ({ - String walletId, - CryptoCurrency coin, - })) { + if (args is ({String walletId, CryptoCurrency coin})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FrostSendView( - walletId: args.walletId, - coin: args.coin, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => FrostSendView(walletId: args.walletId, coin: args.coin), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -617,27 +545,22 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CoinControlView( - walletId: args.item1, - type: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CoinControlView(walletId: args.item1, type: args.item2), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple4?>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CoinControlView( - walletId: args.item1, - type: args.item2, - requestedTotal: args.item3, - selectedUTXOs: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => CoinControlView( + walletId: args.item1, + type: args.item2, + requestedTotal: args.item3, + selectedUTXOs: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -646,12 +569,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => OrdinalsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => OrdinalsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -660,12 +579,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopOrdinalsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopOrdinalsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -674,13 +589,12 @@ class RouteGenerator { if (args is ({Ordinal ordinal, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => OrdinalDetailsView( - walletId: args.walletId, - ordinal: args.ordinal, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => OrdinalDetailsView( + walletId: args.walletId, + ordinal: args.ordinal, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -689,13 +603,12 @@ class RouteGenerator { if (args is ({Ordinal ordinal, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopOrdinalDetailsView( - walletId: args.walletId, - ordinal: args.ordinal, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => DesktopOrdinalDetailsView( + walletId: args.walletId, + ordinal: args.ordinal, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -711,13 +624,10 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => UtxoDetailsView( - walletId: args.item2, - utxoId: args.item1, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => + UtxoDetailsView(walletId: args.item2, utxoId: args.item1), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -726,13 +636,8 @@ class RouteGenerator { if (args is (Id, String)) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NameDetailsView( - walletId: args.$2, - utxoId: args.$1, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => NameDetailsView(walletId: args.$2, utxoId: args.$1), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -741,12 +646,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => PaynymClaimView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => PaynymClaimView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -755,12 +656,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => PaynymHomeView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => PaynymHomeView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -769,12 +666,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddNewPaynymFollowView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AddNewPaynymFollowView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -783,12 +676,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CashFusionView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CashFusionView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -797,12 +686,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NamecoinNamesHomeView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => NamecoinNamesHomeView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -811,13 +696,10 @@ class RouteGenerator { if (args is ({String walletId, UTXO utxo})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ManageDomainView( - walletId: args.walletId, - utxo: args.utxo, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => + ManageDomainView(walletId: args.walletId, utxo: args.utxo), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -826,12 +708,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FusionProgressView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => FusionProgressView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -840,12 +718,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChurningView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChurningView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -854,12 +728,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChurningProgressView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChurningProgressView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -868,12 +738,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopCashFusionView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopCashFusionView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -882,12 +748,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopChurningView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopChurningView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -903,12 +765,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddressBookView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AddressBookView(coin: args), + settings: RouteSettings(name: settings.name), ); } return getRoute( @@ -1012,13 +870,8 @@ class RouteGenerator { if (args is (String, ({List xpubs, String fingerprint}))) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => XPubView( - walletId: args.$1, - xpubData: args.$2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => XPubView(walletId: args.$1, xpubData: args.$2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1027,12 +880,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChangeRepresentativeView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChangeRepresentativeView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1118,12 +967,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreFromEncryptedStringView( - encrypted: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => RestoreFromEncryptedStringView(encrypted: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1139,12 +984,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditCoinUnitsView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditCoinUnitsView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1174,12 +1015,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CoinNodesView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CoinNodesView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1188,14 +1025,13 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NodeDetailsView( - coin: args.item1, - nodeId: args.item2, - popRouteName: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NodeDetailsView( + coin: args.item1, + nodeId: args.item2, + popRouteName: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1204,13 +1040,9 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditNoteView( - txid: args.item1, - walletId: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditNoteView(txid: args.item1, walletId: args.item2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1219,12 +1051,8 @@ class RouteGenerator { if (args is int) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditAddressLabelView( - addressLabelId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditAddressLabelView(addressLabelId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1233,13 +1061,9 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditTradeNoteView( - tradeId: args.item1, - note: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditTradeNoteView(tradeId: args.item1, note: args.item2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1249,15 +1073,14 @@ class RouteGenerator { is Tuple4) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddEditNodeView( - viewType: args.item1, - coin: args.item2, - nodeId: args.item3, - routeOnSuccessOrDelete: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => AddEditNodeView( + viewType: args.item1, + coin: args.item2, + nodeId: args.item3, + routeOnSuccessOrDelete: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1266,12 +1089,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ContactDetailsView( - contactId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ContactDetailsView(contactId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1280,12 +1099,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddNewContactAddressView( - contactId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AddNewContactAddressView(contactId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1294,12 +1109,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditContactNameEmojiView( - contactId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditContactNameEmojiView(contactId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1308,13 +1119,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditContactAddressView( - contactId: args.item1, - addressEntry: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => EditContactAddressView( + contactId: args.item1, + addressEntry: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1323,23 +1133,20 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => const SystemBrightnessThemeSelectionView(), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); case WalletNetworkSettingsView.routeName: if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletNetworkSettingsView( - walletId: args.item1, - initialSyncStatus: args.item2, - initialNodeStatus: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => WalletNetworkSettingsView( + walletId: args.item1, + initialSyncStatus: args.item2, + initialNodeStatus: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1348,91 +1155,88 @@ class RouteGenerator { if (args is ({String walletId, List mnemonic})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonic, - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - frostWalletData: args.frostWalletData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonic, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + frostWalletData: args.frostWalletData, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonic, - KeyDataInterface? keyData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - keyData: args.keyData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonic, + KeyDataInterface? keyData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + keyData: args.keyData, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonic, - KeyDataInterface? keyData, - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletBackupView( - walletId: args.walletId, - mnemonic: args.mnemonic, - frostWalletData: args.frostWalletData, - keyData: args.keyData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonic, + KeyDataInterface? keyData, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => WalletBackupView( + walletId: args.walletId, + mnemonic: args.mnemonic, + frostWalletData: args.frostWalletData, + keyData: args.keyData, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case MobileKeyDataView.routeName: - if (args is ({ - String walletId, - KeyDataInterface keyData, - })) { + if (args is ({String walletId, KeyDataInterface keyData})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => MobileKeyDataView( - walletId: args.walletId, - keyData: args.keyData, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => MobileKeyDataView( + walletId: args.walletId, + keyData: args.keyData, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1441,12 +1245,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletSettingsWalletSettingsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletSettingsWalletSettingsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1455,12 +1255,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RenameWalletView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => RenameWalletView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1469,12 +1265,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteWalletWarningView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DeleteWalletWarningView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1483,12 +1275,8 @@ class RouteGenerator { if (args is AddWalletListEntity) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreateOrRestoreWalletView( - entity: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CreateOrRestoreWalletView(entity: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1497,13 +1285,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NameYourWalletView( - addWalletType: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NameYourWalletView( + addWalletType: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1512,13 +1299,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NewWalletRecoveryPhraseWarningView( - walletName: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NewWalletRecoveryPhraseWarningView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1527,13 +1313,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreOptionsView( - walletName: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreOptionsView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1542,13 +1327,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NewWalletOptionsView( - walletName: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NewWalletOptionsView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1558,39 +1342,38 @@ class RouteGenerator { is Tuple6) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreWalletView( - walletName: args.item1, - coin: args.item2, - seedWordsLength: args.item3, - restoreFromDate: args.item4, - mnemonicPassphrase: args.item5, - enableLelantusScanning: args.item6 ?? false, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => RestoreWalletView( + walletName: args.item1, + coin: args.item2, + seedWordsLength: args.item3, + restoreFromDate: args.item4, + mnemonicPassphrase: args.item5, + enableLelantusScanning: args.item6 ?? false, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case RestoreViewOnlyWalletView.routeName: - if (args is ({ - String walletName, - CryptoCurrency coin, - DateTime? restoreFromDate, - bool enableLelantusScanning, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => RestoreViewOnlyWalletView( - walletName: args.walletName, - coin: args.coin, - restoreFromDate: args.restoreFromDate, - enableLelantusScanning: args.enableLelantusScanning, - ), - settings: RouteSettings( - name: settings.name, - ), + if (args + is ({ + String walletName, + CryptoCurrency coin, + DateTime? restoreFromDate, + bool enableLelantusScanning, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => RestoreViewOnlyWalletView( + walletName: args.walletName, + coin: args.coin, + restoreFromDate: args.restoreFromDate, + enableLelantusScanning: args.enableLelantusScanning, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1599,13 +1382,12 @@ class RouteGenerator { if (args is Tuple2>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NewWalletRecoveryPhraseView( - wallet: args.item1, - mnemonic: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => NewWalletRecoveryPhraseView( + wallet: args.item1, + mnemonic: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1614,13 +1396,12 @@ class RouteGenerator { if (args is Tuple2>) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => VerifyRecoveryPhraseView( - wallet: args.item1, - mnemonic: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => VerifyRecoveryPhraseView( + wallet: args.item1, + mnemonic: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1635,12 +1416,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1649,54 +1426,49 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TransactionDetailsView( - transaction: args.item1, - coin: args.item2, - walletId: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TransactionDetailsView( + transaction: args.item1, + coin: args.item2, + walletId: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case TransactionV2DetailsView.routeName: - if (args is ({ - TransactionV2 tx, - CryptoCurrency coin, - String walletId - })) { + if (args + is ({TransactionV2 tx, CryptoCurrency coin, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TransactionV2DetailsView( - transaction: args.tx, - coin: args.coin, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TransactionV2DetailsView( + transaction: args.tx, + coin: args.coin, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case FusionGroupDetailsView.routeName: - if (args is ({ - List transactions, - CryptoCurrency coin, - String walletId - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => FusionGroupDetailsView( - transactions: args.transactions, - coin: args.coin, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + if (args + is ({ + List transactions, + CryptoCurrency coin, + String walletId, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => FusionGroupDetailsView( + transactions: args.transactions, + coin: args.coin, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1705,12 +1477,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AllTransactionsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AllTransactionsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1719,24 +1487,19 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AllTransactionsV2View( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => AllTransactionsV2View(walletId: args), + settings: RouteSettings(name: settings.name), ); } if (args is ({String walletId, String contractAddress})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AllTransactionsV2View( - walletId: args.walletId, - contractAddress: args.contractAddress, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => AllTransactionsV2View( + walletId: args.walletId, + contractAddress: args.contractAddress, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1745,12 +1508,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TransactionSearchFilterView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => TransactionSearchFilterView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1759,23 +1518,18 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ReceiveView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ReceiveView(walletId: args), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ReceiveView( - walletId: args.item1, - tokenContract: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ReceiveView( + walletId: args.item1, + tokenContract: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1784,12 +1538,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletAddressesView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => WalletAddressesView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1798,13 +1548,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => AddressDetailsView( - walletId: args.item2, - addressId: args.item1, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => AddressDetailsView( + walletId: args.item2, + addressId: args.item1, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1813,49 +1562,37 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.item1, - coin: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SendView(walletId: args.item1, coin: args.item2), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.item1, - coin: args.item2, - autoFillData: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SendView( + walletId: args.item1, + coin: args.item2, + autoFillData: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } else if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.item1, - coin: args.item2, - accountLite: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SendView( + walletId: args.item1, + coin: args.item2, + accountLite: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } else if (args is ({CryptoCurrency coin, String walletId})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendView( - walletId: args.walletId, - coin: args.coin, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SendView(walletId: args.walletId, coin: args.coin), + settings: RouteSettings(name: settings.name), ); } @@ -1865,14 +1602,13 @@ class RouteGenerator { if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenSendView( - walletId: args.item1, - coin: args.item2, - tokenContract: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TokenSendView( + walletId: args.item1, + coin: args.item2, + tokenContract: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1881,14 +1617,13 @@ class RouteGenerator { if (args is (TxData, String, VoidCallback)) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ConfirmTransactionView( - txData: args.$1, - walletId: args.$2, - onSuccess: args.$3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ConfirmTransactionView( + txData: args.$1, + walletId: args.$2, + onSuccess: args.$3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1897,13 +1632,12 @@ class RouteGenerator { if (args is (TxData, String)) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ConfirmNameTransactionView( - txData: args.$1, - walletId: args.$2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => ConfirmNameTransactionView( + txData: args.$1, + walletId: args.$2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1912,40 +1646,38 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Stack( - children: [ - WalletInitiatedExchangeView( - walletId: args.item1, - coin: args.item2, + builder: + (_) => Stack( + children: [ + WalletInitiatedExchangeView( + walletId: args.item1, + coin: args.item2, + ), + // ExchangeLoadingOverlayView( + // unawaitedLoad: args.item3, + // ), + ], ), - // ExchangeLoadingOverlayView( - // unawaitedLoad: args.item3, - // ), - ], - ), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } if (args is Tuple3) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Stack( - children: [ - WalletInitiatedExchangeView( - walletId: args.item1, - coin: args.item2, - contract: args.item3, + builder: + (_) => Stack( + children: [ + WalletInitiatedExchangeView( + walletId: args.item1, + coin: args.item2, + contract: args.item3, + ), + // ExchangeLoadingOverlayView( + // unawaitedLoad: args.item3, + // ), + ], ), - // ExchangeLoadingOverlayView( - // unawaitedLoad: args.item3, - // ), - ], - ), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1954,30 +1686,30 @@ class RouteGenerator { if (args is String?) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => NotificationsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => NotificationsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); case WalletSettingsView.routeName: - if (args is Tuple4) { + if (args + is Tuple4< + String, + CryptoCurrency, + WalletSyncStatus, + NodeConnectionStatus + >) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => WalletSettingsView( - walletId: args.item1, - coin: args.item2, - initialSyncStatus: args.item3, - initialNodeStatus: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => WalletSettingsView( + walletId: args.item1, + coin: args.item2, + initialSyncStatus: args.item3, + initialNodeStatus: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -1986,34 +1718,34 @@ class RouteGenerator { if (args is ({String walletId, List mnemonicWords})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteWalletRecoveryPhraseView( - mnemonic: args.mnemonicWords, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => DeleteWalletRecoveryPhraseView( + mnemonic: args.mnemonicWords, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); - } else if (args is ({ - String walletId, - List mnemonicWords, - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData, - })) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteWalletRecoveryPhraseView( - mnemonic: args.mnemonicWords, - walletId: args.walletId, - frostWalletData: args.frostWalletData, - ), - settings: RouteSettings( - name: settings.name, - ), + } else if (args + is ({ + String walletId, + List mnemonicWords, + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData, + })) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: + (_) => DeleteWalletRecoveryPhraseView( + mnemonic: args.mnemonicWords, + walletId: args.walletId, + frostWalletData: args.frostWalletData, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2022,13 +1754,12 @@ class RouteGenerator { if (args is ({String walletId, ViewOnlyWalletData data})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeleteViewOnlyWalletKeysView( - data: args.data, - walletId: args.walletId, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => DeleteViewOnlyWalletKeysView( + data: args.data, + walletId: args.walletId, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2039,12 +1770,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step1View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step1View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2053,12 +1780,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step2View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step2View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2067,12 +1790,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step3View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step3View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2081,12 +1800,8 @@ class RouteGenerator { if (args is IncompleteExchangeModel) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => Step4View( - model: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => Step4View(model: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2095,15 +1810,14 @@ class RouteGenerator { if (args is Tuple4) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TradeDetailsView( - tradeId: args.item1, - transactionIfSentFromStack: args.item2, - walletId: args.item3, - walletName: args.item4, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TradeDetailsView( + tradeId: args.item1, + transactionIfSentFromStack: args.item2, + walletId: args.item3, + walletName: args.item4, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2112,12 +1826,8 @@ class RouteGenerator { if (args is CryptoCurrency) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => ChooseFromStackView( - coin: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => ChooseFromStackView(coin: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2126,15 +1836,14 @@ class RouteGenerator { if (args is Tuple4) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SendFromView( - coin: args.item1, - amount: args.item2, - trade: args.item4, - address: args.item3, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => SendFromView( + coin: args.item1, + amount: args.item2, + trade: args.item4, + address: args.item3, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2143,13 +1852,12 @@ class RouteGenerator { if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => GenerateUriQrCodeView( - coin: args.item1, - receivingAddress: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => GenerateUriQrCodeView( + coin: args.item1, + receivingAddress: args.item2, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2158,12 +1866,8 @@ class RouteGenerator { if (args is SimplexQuote) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BuyQuotePreviewView( - quote: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => BuyQuotePreviewView(quote: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2173,9 +1877,7 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => LelantusSettingsView(walletId: args), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2185,9 +1887,7 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => RbfSettingsView(walletId: args), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2196,12 +1896,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SparkInfoView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SparkInfoView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2210,12 +1906,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => EditRefreshHeightView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => EditRefreshHeightView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2224,13 +1916,12 @@ class RouteGenerator { if (args is ({String walletId, String domainName})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BuyDomainView( - walletId: args.walletId, - domainName: args.domainName, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => BuyDomainView( + walletId: args.walletId, + domainName: args.domainName, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2240,12 +1931,8 @@ class RouteGenerator { if (args is bool) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => CreatePasswordView( - restoreFromSWB: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => CreatePasswordView(restoreFromSWB: args), + settings: RouteSettings(name: settings.name), ); } return getRoute( @@ -2272,12 +1959,8 @@ class RouteGenerator { if (args is bool) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DeletePasswordWarningView( - shouldCreateNew: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DeletePasswordWarningView(shouldCreateNew: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2315,21 +1998,15 @@ class RouteGenerator { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, builder: (_) => BuyInWalletView(coin: args), - settings: RouteSettings( - name: settings.name, - ), + settings: RouteSettings(name: settings.name), ); } if (args is Tuple2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BuyInWalletView( - coin: args.item1, - contract: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => BuyInWalletView(coin: args.item1, contract: args.item2), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2366,12 +2043,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopWalletView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopWalletView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2380,12 +2053,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopWalletAddressesView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopWalletAddressesView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2394,12 +2063,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => LelantusCoinsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => LelantusCoinsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2408,12 +2073,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SparkCoinsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SparkCoinsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2422,12 +2083,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => DesktopCoinControlView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => DesktopCoinControlView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2436,12 +2093,8 @@ class RouteGenerator { if (args is TransactionV2) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => BoostTransactionView( - transaction: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => BoostTransactionView(transaction: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2531,27 +2184,27 @@ class RouteGenerator { ); case WalletKeysDesktopPopup.routeName: - if (args is ({ - List mnemonic, - String walletId, - ({String keys, String config})? frostData - })) { + if (args + is ({ + List mnemonic, + String walletId, + ({String keys, String config})? frostData, + })) { return FadePageRoute( WalletKeysDesktopPopup( words: args.mnemonic, walletId: args.walletId, frostData: args.frostData, ), - RouteSettings( - name: settings.name, - ), + RouteSettings(name: settings.name), ); - } else if (args is ({ - List mnemonic, - String walletId, - ({String keys, String config})? frostData, - KeyDataInterface? keyData, - })) { + } else if (args + is ({ + List mnemonic, + String walletId, + ({String keys, String config})? frostData, + KeyDataInterface? keyData, + })) { return FadePageRoute( WalletKeysDesktopPopup( words: args.mnemonic, @@ -2559,24 +2212,21 @@ class RouteGenerator { frostData: args.frostData, keyData: args.keyData, ), - RouteSettings( - name: settings.name, - ), + RouteSettings(name: settings.name), ); - } else if (args is ({ - List mnemonic, - String walletId, - KeyDataInterface? keyData, - })) { + } else if (args + is ({ + List mnemonic, + String walletId, + KeyDataInterface? keyData, + })) { return FadePageRoute( WalletKeysDesktopPopup( words: args.mnemonic, walletId: args.walletId, keyData: args.keyData, ), - RouteSettings( - name: settings.name, - ), + RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2584,12 +2234,8 @@ class RouteGenerator { case UnlockWalletKeysDesktop.routeName: if (args is String) { return FadePageRoute( - UnlockWalletKeysDesktop( - walletId: args, - ), - RouteSettings( - name: settings.name, - ), + UnlockWalletKeysDesktop(walletId: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2606,12 +2252,8 @@ class RouteGenerator { case DesktopDeleteWalletDialog.routeName: if (args is String) { return FadePageRoute( - DesktopDeleteWalletDialog( - walletId: args, - ), - RouteSettings( - name: settings.name, - ), + DesktopDeleteWalletDialog(walletId: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2628,12 +2270,8 @@ class RouteGenerator { case DesktopAttentionDeleteWallet.routeName: if (args is String) { return FadePageRoute( - DesktopAttentionDeleteWallet( - walletId: args, - ), - RouteSettings( - name: settings.name, - ), + DesktopAttentionDeleteWallet(walletId: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2650,13 +2288,8 @@ class RouteGenerator { case DeleteWalletKeysPopup.routeName: if (args is Tuple2>) { return FadePageRoute( - DeleteWalletKeysPopup( - walletId: args.item1, - words: args.item2, - ), - RouteSettings( - name: settings.name, - ), + DeleteWalletKeysPopup(walletId: args.item1, words: args.item2), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2673,12 +2306,8 @@ class RouteGenerator { case QRCodeDesktopPopupContent.routeName: if (args is String) { return FadePageRoute( - QRCodeDesktopPopupContent( - value: args, - ), - RouteSettings( - name: settings.name, - ), + QRCodeDesktopPopupContent(value: args), + RouteSettings(name: settings.name), ); // return getRoute( // shouldUseMaterialRoute: useMaterialPageRoute, @@ -2696,12 +2325,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => MyTokensView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => MyTokensView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2724,23 +2349,18 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => TokenView(walletId: args), + settings: RouteSettings(name: settings.name), ); } else if (args is ({String walletId, bool popPrevious})) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => TokenView( - walletId: args.walletId, - popPrevious: args.popPrevious, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: + (_) => TokenView( + walletId: args.walletId, + popPrevious: args.popPrevious, + ), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2749,12 +2369,8 @@ class RouteGenerator { if (args is String) { return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SilentPaymentsView( - walletId: args, - ), - settings: RouteSettings( - name: settings.name, - ), + builder: (_) => SilentPaymentsView(walletId: args), + settings: RouteSettings(name: settings.name), ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); @@ -2800,13 +2416,12 @@ class RouteGenerator { final end = Offset.zero; final curve = Curves.easeInOut; - final tween = - Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); + final tween = Tween( + begin: begin, + end: end, + ).chain(CurveTween(curve: curve)); - return SlideTransition( - position: animation.drive(tween), - child: child, - ); + return SlideTransition(position: animation.drive(tween), child: child); }, ); } @@ -2850,10 +2465,7 @@ class FadePageRoute extends PageRoute { Animation animation, Animation secondaryAnimation, ) { - return FadeTransition( - opacity: animation, - child: child, - ); + return FadeTransition(opacity: animation, child: child); } @override From b85889e033442084d8cb7badf293b86f58582390 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Fri, 11 Apr 2025 01:10:05 -0400 Subject: [PATCH 07/14] good enough --- .../silent_payments/silent_payments_view.dart | 888 ++++++++++-------- 1 file changed, 472 insertions(+), 416 deletions(-) diff --git a/lib/pages/silent_payments/silent_payments_view.dart b/lib/pages/silent_payments/silent_payments_view.dart index d0f00dcc7..df85cb9cc 100644 --- a/lib/pages/silent_payments/silent_payments_view.dart +++ b/lib/pages/silent_payments/silent_payments_view.dart @@ -207,9 +207,6 @@ class _SilentPaymentsViewState extends ConsumerState { if (mounted) { Navigator.of(context, rootNavigator: true).pop(); - // setState(() { - // _isLoading = false; - // }); } } @@ -324,9 +321,6 @@ class _SilentPaymentsViewState extends ConsumerState { if (mounted) { Navigator.of(context, rootNavigator: true).pop(); - // setState(() { - // _isLoading = false; - // }); } } @@ -383,92 +377,387 @@ class _SilentPaymentsViewState extends ConsumerState { overflow: TextOverflow.ellipsis, ), ), - body: ConditionalParent( - condition: !isDesktop, - builder: - (child) => SafeArea( - child: Padding(padding: const EdgeInsets.all(16), child: child), + body: SafeArea(child: _buildContent(isDesktop, colors)), + ); + } + + Widget _buildContent(bool isDesktop, StackColors colors) { + // Use consistent padding approach for both platforms with different values + final double horizontalPadding = isDesktop ? 24 : 16; + final double verticalGap = isDesktop ? 24 : 16; + + return SingleChildScrollView( + padding: EdgeInsets.all(horizontalPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildAddressSection(isDesktop, colors), + + SizedBox(height: verticalGap), + + // Main content - desktop uses rows, mobile uses columns + if (isDesktop) + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: _buildSendSection(isDesktop, colors)), + SizedBox(width: horizontalPadding), + Expanded(child: _buildScanSection(isDesktop, colors)), + ], + ) + else + Column( + children: [ + _buildSendSection(isDesktop, colors), + SizedBox(height: verticalGap), + _buildScanSection(isDesktop, colors), + ], ), - child: Column( - crossAxisAlignment: - isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, + + // Debug information + if (_debugInfo.isNotEmpty) ...[ + SizedBox(height: verticalGap), + _buildDebugSection(isDesktop, colors), + ], + ], + ), + ); + } + + Widget _buildAddressSection(bool isDesktop, StackColors colors) { + // For mobile, if no address is available, return empty widget + if (!isDesktop && _silentPaymentAddress.isEmpty) { + return const SizedBox.shrink(); + } + + // Use RoundedWhiteContainer for desktop, simple column for mobile + Widget content = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( children: [ - if (isDesktop) + Switch( + value: _enabled, + onChanged: (value) { + setState(() { + _enabled = value; + }); + }, + activeColor: colors.accentColorGreen, + ), + const SizedBox(width: 12), + Text( + "Scan for Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.titleBold12(context), + ), + ], + ), + + if (_silentPaymentAddress.isNotEmpty) ...[ + SizedBox(height: isDesktop ? 16 : 12), + Text( + "Your Silent Payment Address:", + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.smallMed12(context), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _silentPaymentAddress, + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ), + ), + const SizedBox(width: 8), + SecondaryButton( + label: "Copy", + buttonHeight: ButtonHeight.m, + iconSpacing: 8, + icon: CopyIcon( + width: 12, + height: 12, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, + ), + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: _silentPaymentAddress), + ); + if (context.mounted) { + await showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + } + }, + ), + ], + ), + ], + ], + ); + + // On desktop, wrap in RoundedWhiteContainer, on mobile use the column directly + return isDesktop + ? RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: content, + ) + : content; + } + + Widget _buildSendSection(bool isDesktop, StackColors colors) { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Send Silent Payment", + style: + isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.titleBold12(context), + ), + const SizedBox(height: 16), + + // Recipient address + Text( + "Recipient Address:", + style: + isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.smallMed12(context), + ), + const SizedBox(height: 8), + TextField( + controller: _recipientAddressController, + decoration: InputDecoration( + hintText: "sp1...", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context) + : STextStyles.smallMed12(context), + minLines: 3, + maxLines: 3, + ), + + const SizedBox(height: 16), + + // Amount + Text( + "Amount (BTC):", + style: + isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.smallMed12(context), + ), + const SizedBox(height: 8), + TextField( + controller: _amountController, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + decoration: InputDecoration( + hintText: "0.0001", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context) + : STextStyles.smallMed12(context), + ), + + const SizedBox(height: 24), + + // Send button + Center( + child: PrimaryButton( + width: 150, + label: "Send", + onPressed: _sendSilentPayment, + ), + ), + + const SizedBox(height: 16), + + // Send process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Sending)", + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.smallMed12( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ Padding( - padding: const EdgeInsets.all(24), - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Row( - children: [ - Switch( - value: _enabled, - onChanged: (value) { - setState(() { - _enabled = value; - }); - }, - activeColor: colors.accentColorGreen, - ), - const SizedBox(width: 12), - Text( - "Scan for Silent Payments", - style: - isDesktop - ? STextStyles.desktopTextMedium( - context, - ) - : STextStyles.titleBold12(context), - ), - ], - ), - ), - ], - ), - if (_silentPaymentAddress.isNotEmpty) ...[ - const SizedBox(height: 16), - Text( - "Your Silent Payment Address:", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Row( + padding: const EdgeInsets.all(16), + child: Text( + "1. Sender gets recipient's Silent Payment address (sp1...)\n" + "2. Sender collects all input public keys (A1, A2, ..., An)\n" + "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" + "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "5. Calculate sender partial secret: s = a_sum * T\n" + "6. Extract B_scan from recipient address\n" + "7. Calculate shared secret: S = B_scan * s\n" + "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "9. Generate output address: B_spend + outputTweak\n" + "10. Send payment to derived address", + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context) + : STextStyles.smallMed12(context), + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildScanSection(bool isDesktop, StackColors colors) { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Received Silent Payments", + style: + isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.titleBold12(context), + ), + const SizedBox(height: 16), + + // Block height + Text( + "Block Height to Scan:", + style: + isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.smallMed12(context), + ), + const SizedBox(height: 8), + TextField( + controller: _blockHeightController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "800000", + filled: true, + fillColor: colors.textFieldDefaultBG, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context) + : STextStyles.smallMed12(context), + ), + + const SizedBox(height: 24), + + // Scan button + Center( + child: PrimaryButton( + width: 150, + label: "Scan", + onPressed: _scanForSilentPayments, + ), + ), + + const SizedBox(height: 16), + + // Detected outputs + if (_detectedOutputs.isNotEmpty) ...[ + Text( + "Detected Silent Payment Outputs:", + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.smallMed12( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _detectedOutputs.map((output) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( children: [ Expanded( - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), - ), - child: Text( - _silentPaymentAddress, - style: STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), + child: Text( + output, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.smallMed12(context), ), ), - const SizedBox(width: 8), SecondaryButton( label: "Copy", - buttonHeight: ButtonHeight.m, - iconSpacing: 8, + buttonHeight: ButtonHeight.s, + iconSpacing: 4, icon: CopyIcon( - width: 12, - height: 12, + width: 10, + height: 10, color: Theme.of(context) .extension()! @@ -476,7 +765,7 @@ class _SilentPaymentsViewState extends ConsumerState { ), onPressed: () async { await Clipboard.setData( - ClipboardData(text: _silentPaymentAddress), + ClipboardData(text: output), ); if (context.mounted) { await showFloatingFlushBar( @@ -490,350 +779,117 @@ class _SilentPaymentsViewState extends ConsumerState { ), ], ), - ], - ], - ), - ), + ); + }).toList(), ), + ), + ], - if (!isDesktop) const SizedBox(height: 24), - - // Main two-column layout - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Left column: Send Silent Payment - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Send Silent Payment", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - - // Recipient address - Text( - "Recipient Address:", - style: STextStyles.desktopTextSmall(context), - ), - const SizedBox(height: 8), - TextField( - controller: _recipientAddressController, - decoration: InputDecoration( - hintText: "sp1...", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - ), - style: STextStyles.desktopTextExtraSmall(context), - minLines: 3, - maxLines: 3, - ), - - const SizedBox(height: 16), - - // Amount - Text( - "Amount (BTC):", - style: STextStyles.desktopTextSmall(context), - ), - const SizedBox(height: 8), - TextField( - controller: _amountController, - keyboardType: const TextInputType.numberWithOptions( - decimal: true, - ), - decoration: InputDecoration( - hintText: "0.0001", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - ), - style: STextStyles.desktopTextExtraSmall(context), - ), - - const SizedBox(height: 24), - - // Send button - Center( - child: PrimaryButton( - width: 150, - label: "Send", - onPressed: _sendSilentPayment, - ), - ), - - const SizedBox(height: 16), + const SizedBox(height: 16), - // Send process explanation - ExpansionTile( - title: Text( - "How Silent Payments Work (Sending)", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text( - "1. Sender gets recipient's Silent Payment address (sp1...)\n" - "2. Sender collects all input public keys (A1, A2, ..., An)\n" - "3. Calculate sum of all input keys: A_sum = A1 + A2 + ... + An\n" - "4. Compute T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" - "5. Calculate sender partial secret: s = a_sum * T\n" - "6. Extract B_scan from recipient address\n" - "7. Calculate shared secret: S = B_scan * s\n" - "8. For each output i, calculate outputTweak = TaggedHash(S || i)\n" - "9. Generate output address: B_spend + outputTweak\n" - "10. Send payment to derived address", - style: STextStyles.desktopTextExtraSmall( - context, - ), - ), - ), - ], - ), - ], - ), - ), + // Receive process explanation + ExpansionTile( + title: Text( + "How Silent Payments Work (Receiving)", + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.smallMed12( + context, + ).copyWith(fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text( + "1. Recipient scans each transaction in new blocks\n" + "2. For each transaction, compute A_sum from input public keys\n" + "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" + "4. Calculate receiver partial secret: r = T * b_scan\n" + "5. Calculate shared secret: S = A_sum * r\n" + "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" + "7. Derive expected output: B_spend + outputTweak\n" + "8. Check if any transaction outputs match expected addresses\n" + "9. If match found, calculate private key: b_spend + outputTweak", + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context) + : STextStyles.smallMed12(context), ), + ), + ], + ), + ], + ), + ); + } - const SizedBox(width: 24), - - // Right column: Receive Silent Payment - Expanded( - child: RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Received Silent Payments", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - - // Block height - Text( - "Block Height to Scan:", - style: STextStyles.desktopTextSmall(context), - ), - const SizedBox(height: 8), - TextField( - controller: _blockHeightController, - keyboardType: TextInputType.number, - decoration: InputDecoration( - hintText: "800000", - filled: true, - fillColor: colors.textFieldDefaultBG, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - ), - style: STextStyles.desktopTextExtraSmall(context), - ), - - const SizedBox(height: 24), - - // Scan button - Center( - child: PrimaryButton( + Widget _buildDebugSection(bool isDesktop, StackColors colors) { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Debug Information", + style: + isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.titleBold12(context), + ), + const SizedBox(height: 16), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.textFieldDefaultBG, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _debugInfo.entries.map((entry) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( width: 150, - label: "Scan", - onPressed: _scanForSilentPayments, - ), - ), - - const SizedBox(height: 16), - - // Detected outputs - if (_detectedOutputs.isNotEmpty) ...[ - Text( - "Detected Silent Payment Outputs:", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), + child: Text( + "${entry.key}:", + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith(fontWeight: FontWeight.bold) + : STextStyles.smallMed12( + context, + ).copyWith(fontWeight: FontWeight.bold), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: - _detectedOutputs.map((output) { - return Padding( - padding: const EdgeInsets.symmetric( - vertical: 4, - ), - child: Row( - children: [ - Expanded( - child: Text( - output, - style: - STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), - ), - SecondaryButton( - label: "Copy", - buttonHeight: ButtonHeight.s, - iconSpacing: 4, - icon: CopyIcon( - width: 10, - height: 10, - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - onPressed: () async { - await Clipboard.setData( - ClipboardData(text: output), - ); - if (context.mounted) { - await showFloatingFlushBar( - type: FlushBarType.info, - message: - "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - } - }, - ), - ], - ), - ); - }).toList(), + ), + Expanded( + child: Text( + entry.value, + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ) + : STextStyles.smallMed12(context), ), ), ], - - const SizedBox(height: 16), - - // Receive process explanation - ExpansionTile( - title: Text( - "How Silent Payments Work (Receiving)", - style: STextStyles.desktopTextSmall( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text( - "1. Recipient scans each transaction in new blocks\n" - "2. For each transaction, compute A_sum from input public keys\n" - "3. Calculate T = SHA256(TaggedHash(lowest_outpoint || A_sum))\n" - "4. Calculate receiver partial secret: r = T * b_scan\n" - "5. Calculate shared secret: S = A_sum * r\n" - "6. For each output i, calculate outputTweak = TaggedHash(S || i)\n" - "7. Derive expected output: B_spend + outputTweak\n" - "8. Check if any transaction outputs match expected addresses\n" - "9. If match found, calculate private key: b_spend + outputTweak", - style: STextStyles.desktopTextExtraSmall( - context, - ), - ), - ), - ], - ), - ], - ), - ), - ), - ], - ), - - const SizedBox(height: 24), - - // Debug information section - if (_debugInfo.isNotEmpty) - RoundedWhiteContainer( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Debug Information", - style: STextStyles.desktopTextMedium( - context, - ).copyWith(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: colors.textFieldDefaultBG, - borderRadius: BorderRadius.circular(8), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: - _debugInfo.entries.map((entry) { - return Padding( - padding: const EdgeInsets.symmetric( - vertical: 4, - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 150, - child: Text( - "${entry.key}:", - style: - STextStyles.desktopTextExtraSmall( - context, - ).copyWith( - fontWeight: FontWeight.bold, - ), - ), - ), - Expanded( - child: Text( - entry.value, - style: - STextStyles.desktopTextExtraSmall( - context, - ), - ), - ), - ], - ), - ); - }).toList(), - ), - ), - ], - ), - ), - ], - ), + ); + }).toList(), + ), + ), + ], ), ); } From 81777d4c36506adfbd4acb25f5e1e48ba15f30fd Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Sun, 27 Apr 2025 21:04:10 -0400 Subject: [PATCH 08/14] silent payment isar models --- .../silent_payment_config.dart | 84 + .../silent_payment_config.g.dart | 949 ++++++ .../silent_payments/silent_payment_data.dart | 76 + .../silent_payment_data.g.dart | 945 ++++++ .../silent_payment_metadata.dart | 72 + .../silent_payment_metadata.g.dart | 1516 +++++++++ .../silent_payment_output.dart | 172 ++ .../silent_payment_output.g.dart | 2752 +++++++++++++++++ 8 files changed, 6566 insertions(+) create mode 100644 lib/models/isar/models/silent_payments/silent_payment_config.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_config.g.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_data.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_data.g.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_metadata.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_output.dart create mode 100644 lib/models/isar/models/silent_payments/silent_payment_output.g.dart diff --git a/lib/models/isar/models/silent_payments/silent_payment_config.dart b/lib/models/isar/models/silent_payments/silent_payment_config.dart new file mode 100644 index 000000000..7557619f7 --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_config.dart @@ -0,0 +1,84 @@ +import 'dart:convert'; +import 'package:isar/isar.dart'; +import '../../../../wallets/isar/isar_id_interface.dart'; + +part 'silent_payment_config.g.dart'; + +@Collection(accessor: "silentPaymentConfig", inheritance: false) +class SilentPaymentConfig implements IsarId { + @override + Id id = Isar.autoIncrement; + + @Index(unique: true) + final String walletId; + + final bool isEnabled; + + final int lastScannedHeight; + + // Store any computed labels for efficient lookup + final String? labelMapJsonString; + + @ignore + Map? get labelMap => + labelMapJsonString == null + ? null + : Map.from(jsonDecode(labelMapJsonString!) as Map); + + SilentPaymentConfig({ + required this.walletId, + this.isEnabled = false, + this.lastScannedHeight = 0, + this.labelMapJsonString, + }); + + SilentPaymentConfig copyWith({ + bool? isEnabled, + int? lastScannedHeight, + String? labelMapJsonString, + }) { + return SilentPaymentConfig( + walletId: walletId, + isEnabled: isEnabled ?? this.isEnabled, + lastScannedHeight: lastScannedHeight ?? this.lastScannedHeight, + labelMapJsonString: labelMapJsonString ?? this.labelMapJsonString, + )..id = id; + } + + Future updateEnabled({ + required bool enabled, + required Isar isar, + }) async { + if (isEnabled != enabled) { + await isar.writeTxn(() async { + await isar.silentPaymentConfig.put(copyWith(isEnabled: enabled)); + }); + } + } + + Future updateLastScannedHeight({ + required int height, + required Isar isar, + }) async { + if (lastScannedHeight != height) { + await isar.writeTxn(() async { + await isar.silentPaymentConfig.put(copyWith(lastScannedHeight: height)); + }); + } + } + + Future updateLabelMap({ + required Map newLabelMap, + required Isar isar, + }) async { + final encodedMap = jsonEncode(newLabelMap); + + if (labelMapJsonString != encodedMap) { + await isar.writeTxn(() async { + await isar.silentPaymentConfig.put( + copyWith(labelMapJsonString: encodedMap), + ); + }); + } + } +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_config.g.dart b/lib/models/isar/models/silent_payments/silent_payment_config.g.dart new file mode 100644 index 000000000..c1673021e --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_config.g.dart @@ -0,0 +1,949 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'silent_payment_config.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetSilentPaymentConfigCollection on Isar { + IsarCollection get silentPaymentConfig => + this.collection(); +} + +const SilentPaymentConfigSchema = CollectionSchema( + name: r'SilentPaymentConfig', + id: 8185245117812277101, + properties: { + r'isEnabled': PropertySchema( + id: 0, + name: r'isEnabled', + type: IsarType.bool, + ), + r'labelMapJsonString': PropertySchema( + id: 1, + name: r'labelMapJsonString', + type: IsarType.string, + ), + r'lastScannedHeight': PropertySchema( + id: 2, + name: r'lastScannedHeight', + type: IsarType.long, + ), + r'walletId': PropertySchema( + id: 3, + name: r'walletId', + type: IsarType.string, + ) + }, + estimateSize: _silentPaymentConfigEstimateSize, + serialize: _silentPaymentConfigSerialize, + deserialize: _silentPaymentConfigDeserialize, + deserializeProp: _silentPaymentConfigDeserializeProp, + idName: r'id', + indexes: { + r'walletId': IndexSchema( + id: -1783113319798776304, + name: r'walletId', + unique: true, + replace: false, + properties: [ + IndexPropertySchema( + name: r'walletId', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _silentPaymentConfigGetId, + getLinks: _silentPaymentConfigGetLinks, + attach: _silentPaymentConfigAttach, + version: '3.1.8', +); + +int _silentPaymentConfigEstimateSize( + SilentPaymentConfig object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.labelMapJsonString; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.walletId.length * 3; + return bytesCount; +} + +void _silentPaymentConfigSerialize( + SilentPaymentConfig object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeBool(offsets[0], object.isEnabled); + writer.writeString(offsets[1], object.labelMapJsonString); + writer.writeLong(offsets[2], object.lastScannedHeight); + writer.writeString(offsets[3], object.walletId); +} + +SilentPaymentConfig _silentPaymentConfigDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = SilentPaymentConfig( + isEnabled: reader.readBoolOrNull(offsets[0]) ?? false, + labelMapJsonString: reader.readStringOrNull(offsets[1]), + lastScannedHeight: reader.readLongOrNull(offsets[2]) ?? 0, + walletId: reader.readString(offsets[3]), + ); + object.id = id; + return object; +} + +P _silentPaymentConfigDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readBoolOrNull(offset) ?? false) as P; + case 1: + return (reader.readStringOrNull(offset)) as P; + case 2: + return (reader.readLongOrNull(offset) ?? 0) as P; + case 3: + return (reader.readString(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _silentPaymentConfigGetId(SilentPaymentConfig object) { + return object.id; +} + +List> _silentPaymentConfigGetLinks( + SilentPaymentConfig object) { + return []; +} + +void _silentPaymentConfigAttach( + IsarCollection col, Id id, SilentPaymentConfig object) { + object.id = id; +} + +extension SilentPaymentConfigByIndex on IsarCollection { + Future getByWalletId(String walletId) { + return getByIndex(r'walletId', [walletId]); + } + + SilentPaymentConfig? getByWalletIdSync(String walletId) { + return getByIndexSync(r'walletId', [walletId]); + } + + Future deleteByWalletId(String walletId) { + return deleteByIndex(r'walletId', [walletId]); + } + + bool deleteByWalletIdSync(String walletId) { + return deleteByIndexSync(r'walletId', [walletId]); + } + + Future> getAllByWalletId( + List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return getAllByIndex(r'walletId', values); + } + + List getAllByWalletIdSync(List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return getAllByIndexSync(r'walletId', values); + } + + Future deleteAllByWalletId(List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return deleteAllByIndex(r'walletId', values); + } + + int deleteAllByWalletIdSync(List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return deleteAllByIndexSync(r'walletId', values); + } + + Future putByWalletId(SilentPaymentConfig object) { + return putByIndex(r'walletId', object); + } + + Id putByWalletIdSync(SilentPaymentConfig object, {bool saveLinks = true}) { + return putByIndexSync(r'walletId', object, saveLinks: saveLinks); + } + + Future> putAllByWalletId(List objects) { + return putAllByIndex(r'walletId', objects); + } + + List putAllByWalletIdSync(List objects, + {bool saveLinks = true}) { + return putAllByIndexSync(r'walletId', objects, saveLinks: saveLinks); + } +} + +extension SilentPaymentConfigQueryWhereSort + on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension SilentPaymentConfigQueryWhere + on QueryBuilder { + QueryBuilder + idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder + idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder + idGreaterThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder + idLessThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder + idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualTo(String walletId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId', + value: [walletId], + )); + }); + } + + QueryBuilder + walletIdNotEqualTo(String walletId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [], + upper: [walletId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [walletId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [walletId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [], + upper: [walletId], + includeUpper: false, + )); + } + }); + } +} + +extension SilentPaymentConfigQueryFilter on QueryBuilder { + QueryBuilder + idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + isEnabledEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isEnabled', + value: value, + )); + }); + } + + QueryBuilder + labelMapJsonStringIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'labelMapJsonString', + )); + }); + } + + QueryBuilder + labelMapJsonStringIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'labelMapJsonString', + )); + }); + } + + QueryBuilder + labelMapJsonStringEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'labelMapJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'labelMapJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'labelMapJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'labelMapJsonString', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'labelMapJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'labelMapJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'labelMapJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'labelMapJsonString', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMapJsonStringIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'labelMapJsonString', + value: '', + )); + }); + } + + QueryBuilder + labelMapJsonStringIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'labelMapJsonString', + value: '', + )); + }); + } + + QueryBuilder + lastScannedHeightEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'lastScannedHeight', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'lastScannedHeight', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'lastScannedHeight', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'lastScannedHeight', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'walletId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'walletId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: '', + )); + }); + } + + QueryBuilder + walletIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'walletId', + value: '', + )); + }); + } +} + +extension SilentPaymentConfigQueryObject on QueryBuilder {} + +extension SilentPaymentConfigQueryLinks on QueryBuilder {} + +extension SilentPaymentConfigQuerySortBy + on QueryBuilder { + QueryBuilder + sortByIsEnabled() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.asc); + }); + } + + QueryBuilder + sortByIsEnabledDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.desc); + }); + } + + QueryBuilder + sortByLabelMapJsonString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'labelMapJsonString', Sort.asc); + }); + } + + QueryBuilder + sortByLabelMapJsonStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'labelMapJsonString', Sort.desc); + }); + } + + QueryBuilder + sortByLastScannedHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.asc); + }); + } + + QueryBuilder + sortByLastScannedHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.desc); + }); + } + + QueryBuilder + sortByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + sortByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentConfigQuerySortThenBy + on QueryBuilder { + QueryBuilder + thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByIsEnabled() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.asc); + }); + } + + QueryBuilder + thenByIsEnabledDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.desc); + }); + } + + QueryBuilder + thenByLabelMapJsonString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'labelMapJsonString', Sort.asc); + }); + } + + QueryBuilder + thenByLabelMapJsonStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'labelMapJsonString', Sort.desc); + }); + } + + QueryBuilder + thenByLastScannedHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.asc); + }); + } + + QueryBuilder + thenByLastScannedHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.desc); + }); + } + + QueryBuilder + thenByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + thenByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentConfigQueryWhereDistinct + on QueryBuilder { + QueryBuilder + distinctByIsEnabled() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isEnabled'); + }); + } + + QueryBuilder + distinctByLabelMapJsonString({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'labelMapJsonString', + caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByLastScannedHeight() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'lastScannedHeight'); + }); + } + + QueryBuilder + distinctByWalletId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); + }); + } +} + +extension SilentPaymentConfigQueryProperty + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + isEnabledProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isEnabled'); + }); + } + + QueryBuilder + labelMapJsonStringProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'labelMapJsonString'); + }); + } + + QueryBuilder + lastScannedHeightProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'lastScannedHeight'); + }); + } + + QueryBuilder + walletIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'walletId'); + }); + } +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_data.dart b/lib/models/isar/models/silent_payments/silent_payment_data.dart new file mode 100644 index 000000000..f650991be --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_data.dart @@ -0,0 +1,76 @@ +// NOTE: might delete later to use config instead + +import 'dart:convert'; + +import 'package:isar/isar.dart'; +import '../../../../wallets/isar/isar_id_interface.dart'; + +part 'silent_payment_data.g.dart'; + +@Collection(accessor: "silentPaymentData", inheritance: false) +class SilentPaymentData implements IsarId { + @override + Id id = Isar.autoIncrement; + + @Index(unique: true, replace: false) + final String walletId; + + // Whether this wallet has silent payments scanning enabled + final bool isEnabled; + + // The last block height scanned for silent payments + final int lastScannedHeight; + + // Store any additional data as JSON + final String? metadataJsonString; + + // Convenience getters + @ignore + Map get metadata => + metadataJsonString == null + ? {} + : Map.from(jsonDecode(metadataJsonString!) as Map); + + SilentPaymentData({ + required this.walletId, + this.isEnabled = false, + this.lastScannedHeight = 0, + this.metadataJsonString, + }); + + // Modification methods + SilentPaymentData copyWith({ + bool? isEnabled, + int? lastScannedHeight, + String? metadataJsonString, + }) { + return SilentPaymentData( + walletId: walletId, + isEnabled: isEnabled ?? this.isEnabled, + lastScannedHeight: lastScannedHeight ?? this.lastScannedHeight, + metadataJsonString: metadataJsonString ?? this.metadataJsonString, + )..id = id; + } + + // Database update methods + Future updateEnabled({ + required bool enabled, + required Isar isar, + }) async { + final data = + await isar.silentPaymentData + .where() + .walletIdEqualTo(walletId) + .findFirst() ?? + this; + + if (data.isEnabled != enabled) { + await isar.writeTxn(() async { + await isar.silentPaymentData.delete(data.id); + await isar.silentPaymentData.put(data.copyWith(isEnabled: enabled)); + }); + } + } + + // Similar methods for updating lastScannedHeight, etc. +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_data.g.dart b/lib/models/isar/models/silent_payments/silent_payment_data.g.dart new file mode 100644 index 000000000..7a468e0eb --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_data.g.dart @@ -0,0 +1,945 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'silent_payment_data.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetSilentPaymentDataCollection on Isar { + IsarCollection get silentPaymentData => this.collection(); +} + +const SilentPaymentDataSchema = CollectionSchema( + name: r'SilentPaymentData', + id: -2677381250855078109, + properties: { + r'isEnabled': PropertySchema( + id: 0, + name: r'isEnabled', + type: IsarType.bool, + ), + r'lastScannedHeight': PropertySchema( + id: 1, + name: r'lastScannedHeight', + type: IsarType.long, + ), + r'metadataJsonString': PropertySchema( + id: 2, + name: r'metadataJsonString', + type: IsarType.string, + ), + r'walletId': PropertySchema( + id: 3, + name: r'walletId', + type: IsarType.string, + ) + }, + estimateSize: _silentPaymentDataEstimateSize, + serialize: _silentPaymentDataSerialize, + deserialize: _silentPaymentDataDeserialize, + deserializeProp: _silentPaymentDataDeserializeProp, + idName: r'id', + indexes: { + r'walletId': IndexSchema( + id: -1783113319798776304, + name: r'walletId', + unique: true, + replace: false, + properties: [ + IndexPropertySchema( + name: r'walletId', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _silentPaymentDataGetId, + getLinks: _silentPaymentDataGetLinks, + attach: _silentPaymentDataAttach, + version: '3.1.8', +); + +int _silentPaymentDataEstimateSize( + SilentPaymentData object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.metadataJsonString; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.walletId.length * 3; + return bytesCount; +} + +void _silentPaymentDataSerialize( + SilentPaymentData object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeBool(offsets[0], object.isEnabled); + writer.writeLong(offsets[1], object.lastScannedHeight); + writer.writeString(offsets[2], object.metadataJsonString); + writer.writeString(offsets[3], object.walletId); +} + +SilentPaymentData _silentPaymentDataDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = SilentPaymentData( + isEnabled: reader.readBoolOrNull(offsets[0]) ?? false, + lastScannedHeight: reader.readLongOrNull(offsets[1]) ?? 0, + metadataJsonString: reader.readStringOrNull(offsets[2]), + walletId: reader.readString(offsets[3]), + ); + object.id = id; + return object; +} + +P _silentPaymentDataDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readBoolOrNull(offset) ?? false) as P; + case 1: + return (reader.readLongOrNull(offset) ?? 0) as P; + case 2: + return (reader.readStringOrNull(offset)) as P; + case 3: + return (reader.readString(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _silentPaymentDataGetId(SilentPaymentData object) { + return object.id; +} + +List> _silentPaymentDataGetLinks( + SilentPaymentData object) { + return []; +} + +void _silentPaymentDataAttach( + IsarCollection col, Id id, SilentPaymentData object) { + object.id = id; +} + +extension SilentPaymentDataByIndex on IsarCollection { + Future getByWalletId(String walletId) { + return getByIndex(r'walletId', [walletId]); + } + + SilentPaymentData? getByWalletIdSync(String walletId) { + return getByIndexSync(r'walletId', [walletId]); + } + + Future deleteByWalletId(String walletId) { + return deleteByIndex(r'walletId', [walletId]); + } + + bool deleteByWalletIdSync(String walletId) { + return deleteByIndexSync(r'walletId', [walletId]); + } + + Future> getAllByWalletId( + List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return getAllByIndex(r'walletId', values); + } + + List getAllByWalletIdSync(List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return getAllByIndexSync(r'walletId', values); + } + + Future deleteAllByWalletId(List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return deleteAllByIndex(r'walletId', values); + } + + int deleteAllByWalletIdSync(List walletIdValues) { + final values = walletIdValues.map((e) => [e]).toList(); + return deleteAllByIndexSync(r'walletId', values); + } + + Future putByWalletId(SilentPaymentData object) { + return putByIndex(r'walletId', object); + } + + Id putByWalletIdSync(SilentPaymentData object, {bool saveLinks = true}) { + return putByIndexSync(r'walletId', object, saveLinks: saveLinks); + } + + Future> putAllByWalletId(List objects) { + return putAllByIndex(r'walletId', objects); + } + + List putAllByWalletIdSync(List objects, + {bool saveLinks = true}) { + return putAllByIndexSync(r'walletId', objects, saveLinks: saveLinks); + } +} + +extension SilentPaymentDataQueryWhereSort + on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension SilentPaymentDataQueryWhere + on QueryBuilder { + QueryBuilder + idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder + idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder + idGreaterThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder + idLessThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder + idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualTo(String walletId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId', + value: [walletId], + )); + }); + } + + QueryBuilder + walletIdNotEqualTo(String walletId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [], + upper: [walletId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [walletId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [walletId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [], + upper: [walletId], + includeUpper: false, + )); + } + }); + } +} + +extension SilentPaymentDataQueryFilter + on QueryBuilder { + QueryBuilder + idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + isEnabledEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isEnabled', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'lastScannedHeight', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'lastScannedHeight', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'lastScannedHeight', + value: value, + )); + }); + } + + QueryBuilder + lastScannedHeightBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'lastScannedHeight', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + metadataJsonStringIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'metadataJsonString', + )); + }); + } + + QueryBuilder + metadataJsonStringIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'metadataJsonString', + )); + }); + } + + QueryBuilder + metadataJsonStringEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'metadataJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'metadataJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'metadataJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'metadataJsonString', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'metadataJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'metadataJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'metadataJsonString', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'metadataJsonString', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + metadataJsonStringIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'metadataJsonString', + value: '', + )); + }); + } + + QueryBuilder + metadataJsonStringIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'metadataJsonString', + value: '', + )); + }); + } + + QueryBuilder + walletIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'walletId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'walletId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: '', + )); + }); + } + + QueryBuilder + walletIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'walletId', + value: '', + )); + }); + } +} + +extension SilentPaymentDataQueryObject + on QueryBuilder {} + +extension SilentPaymentDataQueryLinks + on QueryBuilder {} + +extension SilentPaymentDataQuerySortBy + on QueryBuilder { + QueryBuilder + sortByIsEnabled() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.asc); + }); + } + + QueryBuilder + sortByIsEnabledDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.desc); + }); + } + + QueryBuilder + sortByLastScannedHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.asc); + }); + } + + QueryBuilder + sortByLastScannedHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.desc); + }); + } + + QueryBuilder + sortByMetadataJsonString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'metadataJsonString', Sort.asc); + }); + } + + QueryBuilder + sortByMetadataJsonStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'metadataJsonString', Sort.desc); + }); + } + + QueryBuilder + sortByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + sortByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentDataQuerySortThenBy + on QueryBuilder { + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByIsEnabled() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.asc); + }); + } + + QueryBuilder + thenByIsEnabledDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isEnabled', Sort.desc); + }); + } + + QueryBuilder + thenByLastScannedHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.asc); + }); + } + + QueryBuilder + thenByLastScannedHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'lastScannedHeight', Sort.desc); + }); + } + + QueryBuilder + thenByMetadataJsonString() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'metadataJsonString', Sort.asc); + }); + } + + QueryBuilder + thenByMetadataJsonStringDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'metadataJsonString', Sort.desc); + }); + } + + QueryBuilder + thenByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + thenByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentDataQueryWhereDistinct + on QueryBuilder { + QueryBuilder + distinctByIsEnabled() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isEnabled'); + }); + } + + QueryBuilder + distinctByLastScannedHeight() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'lastScannedHeight'); + }); + } + + QueryBuilder + distinctByMetadataJsonString({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'metadataJsonString', + caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByWalletId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); + }); + } +} + +extension SilentPaymentDataQueryProperty + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder isEnabledProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isEnabled'); + }); + } + + QueryBuilder + lastScannedHeightProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'lastScannedHeight'); + }); + } + + QueryBuilder + metadataJsonStringProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'metadataJsonString'); + }); + } + + QueryBuilder walletIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'walletId'); + }); + } +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_metadata.dart b/lib/models/isar/models/silent_payments/silent_payment_metadata.dart new file mode 100644 index 000000000..b14cc7dd6 --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_metadata.dart @@ -0,0 +1,72 @@ +import 'package:isar/isar.dart'; +import '../../../../wallets/isar/isar_id_interface.dart'; + +part 'silent_payment_metadata.g.dart'; + +@Collection(accessor: "silentPaymentMetadata", inheritance: false) +class SilentPaymentMetadata implements IsarId { + @override + Id id = Isar.autoIncrement; + + // Link to the UTXO this metadata is associated with + @Index(unique: true) + final int utxoId; + + // The wallet ID for efficient querying + @Index() + final String walletId; + + // Private key tweak needed to spend this output + final String privKeyTweak; + + // Optional label for the silent payment + final String? label; + + // Shared secret used to derive this output (optional - for reference only) + final String? sharedSecret; + + // Output index in the set of outputs derived from the same shared secret + final int outputIndex; + + SilentPaymentMetadata({ + required this.utxoId, + required this.walletId, + required this.privKeyTweak, + required this.outputIndex, + this.label, + this.sharedSecret, + }); + + SilentPaymentMetadata copyWith({ + int? utxoId, + String? walletId, + String? privKeyTweak, + int? outputIndex, + String? label, + String? sharedSecret, + }) { + return SilentPaymentMetadata( + utxoId: utxoId ?? this.utxoId, + walletId: walletId ?? this.walletId, + privKeyTweak: privKeyTweak ?? this.privKeyTweak, + outputIndex: outputIndex ?? this.outputIndex, + label: label ?? this.label, + sharedSecret: sharedSecret ?? this.sharedSecret, + )..id = id; + } + + Future updateLabel({ + required Isar isar, + required String? newLabel, + }) async { + final thisMetadata = await isar.silentPaymentMetadata.get(id) ?? this; + + if (thisMetadata.label != newLabel) { + await isar.writeTxn(() async { + await isar.silentPaymentMetadata.put( + thisMetadata.copyWith(label: newLabel), + ); + }); + } + } +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart b/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart new file mode 100644 index 000000000..bb7a967ea --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart @@ -0,0 +1,1516 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'silent_payment_metadata.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetSilentPaymentMetadataCollection on Isar { + IsarCollection get silentPaymentMetadata => + this.collection(); +} + +const SilentPaymentMetadataSchema = CollectionSchema( + name: r'SilentPaymentMetadata', + id: -6055173424802135633, + properties: { + r'label': PropertySchema( + id: 0, + name: r'label', + type: IsarType.string, + ), + r'outputIndex': PropertySchema( + id: 1, + name: r'outputIndex', + type: IsarType.long, + ), + r'privKeyTweak': PropertySchema( + id: 2, + name: r'privKeyTweak', + type: IsarType.string, + ), + r'sharedSecret': PropertySchema( + id: 3, + name: r'sharedSecret', + type: IsarType.string, + ), + r'utxoId': PropertySchema( + id: 4, + name: r'utxoId', + type: IsarType.long, + ), + r'walletId': PropertySchema( + id: 5, + name: r'walletId', + type: IsarType.string, + ) + }, + estimateSize: _silentPaymentMetadataEstimateSize, + serialize: _silentPaymentMetadataSerialize, + deserialize: _silentPaymentMetadataDeserialize, + deserializeProp: _silentPaymentMetadataDeserializeProp, + idName: r'id', + indexes: { + r'utxoId': IndexSchema( + id: 5379991336603932725, + name: r'utxoId', + unique: true, + replace: false, + properties: [ + IndexPropertySchema( + name: r'utxoId', + type: IndexType.value, + caseSensitive: false, + ) + ], + ), + r'walletId': IndexSchema( + id: -1783113319798776304, + name: r'walletId', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'walletId', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _silentPaymentMetadataGetId, + getLinks: _silentPaymentMetadataGetLinks, + attach: _silentPaymentMetadataAttach, + version: '3.1.8', +); + +int _silentPaymentMetadataEstimateSize( + SilentPaymentMetadata object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.label; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.privKeyTweak.length * 3; + { + final value = object.sharedSecret; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.walletId.length * 3; + return bytesCount; +} + +void _silentPaymentMetadataSerialize( + SilentPaymentMetadata object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeString(offsets[0], object.label); + writer.writeLong(offsets[1], object.outputIndex); + writer.writeString(offsets[2], object.privKeyTweak); + writer.writeString(offsets[3], object.sharedSecret); + writer.writeLong(offsets[4], object.utxoId); + writer.writeString(offsets[5], object.walletId); +} + +SilentPaymentMetadata _silentPaymentMetadataDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = SilentPaymentMetadata( + label: reader.readStringOrNull(offsets[0]), + outputIndex: reader.readLong(offsets[1]), + privKeyTweak: reader.readString(offsets[2]), + sharedSecret: reader.readStringOrNull(offsets[3]), + utxoId: reader.readLong(offsets[4]), + walletId: reader.readString(offsets[5]), + ); + object.id = id; + return object; +} + +P _silentPaymentMetadataDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readStringOrNull(offset)) as P; + case 1: + return (reader.readLong(offset)) as P; + case 2: + return (reader.readString(offset)) as P; + case 3: + return (reader.readStringOrNull(offset)) as P; + case 4: + return (reader.readLong(offset)) as P; + case 5: + return (reader.readString(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _silentPaymentMetadataGetId(SilentPaymentMetadata object) { + return object.id; +} + +List> _silentPaymentMetadataGetLinks( + SilentPaymentMetadata object) { + return []; +} + +void _silentPaymentMetadataAttach( + IsarCollection col, Id id, SilentPaymentMetadata object) { + object.id = id; +} + +extension SilentPaymentMetadataByIndex + on IsarCollection { + Future getByUtxoId(int utxoId) { + return getByIndex(r'utxoId', [utxoId]); + } + + SilentPaymentMetadata? getByUtxoIdSync(int utxoId) { + return getByIndexSync(r'utxoId', [utxoId]); + } + + Future deleteByUtxoId(int utxoId) { + return deleteByIndex(r'utxoId', [utxoId]); + } + + bool deleteByUtxoIdSync(int utxoId) { + return deleteByIndexSync(r'utxoId', [utxoId]); + } + + Future> getAllByUtxoId(List utxoIdValues) { + final values = utxoIdValues.map((e) => [e]).toList(); + return getAllByIndex(r'utxoId', values); + } + + List getAllByUtxoIdSync(List utxoIdValues) { + final values = utxoIdValues.map((e) => [e]).toList(); + return getAllByIndexSync(r'utxoId', values); + } + + Future deleteAllByUtxoId(List utxoIdValues) { + final values = utxoIdValues.map((e) => [e]).toList(); + return deleteAllByIndex(r'utxoId', values); + } + + int deleteAllByUtxoIdSync(List utxoIdValues) { + final values = utxoIdValues.map((e) => [e]).toList(); + return deleteAllByIndexSync(r'utxoId', values); + } + + Future putByUtxoId(SilentPaymentMetadata object) { + return putByIndex(r'utxoId', object); + } + + Id putByUtxoIdSync(SilentPaymentMetadata object, {bool saveLinks = true}) { + return putByIndexSync(r'utxoId', object, saveLinks: saveLinks); + } + + Future> putAllByUtxoId(List objects) { + return putAllByIndex(r'utxoId', objects); + } + + List putAllByUtxoIdSync(List objects, + {bool saveLinks = true}) { + return putAllByIndexSync(r'utxoId', objects, saveLinks: saveLinks); + } +} + +extension SilentPaymentMetadataQueryWhereSort + on QueryBuilder { + QueryBuilder + anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } + + QueryBuilder + anyUtxoId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + const IndexWhereClause.any(indexName: r'utxoId'), + ); + }); + } +} + +extension SilentPaymentMetadataQueryWhere on QueryBuilder { + QueryBuilder + idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder + idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder + idGreaterThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder + idLessThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder + idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + utxoIdEqualTo(int utxoId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'utxoId', + value: [utxoId], + )); + }); + } + + QueryBuilder + utxoIdNotEqualTo(int utxoId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [], + upper: [utxoId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [utxoId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [utxoId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [], + upper: [utxoId], + includeUpper: false, + )); + } + }); + } + + QueryBuilder + utxoIdGreaterThan( + int utxoId, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [utxoId], + includeLower: include, + upper: [], + )); + }); + } + + QueryBuilder + utxoIdLessThan( + int utxoId, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [], + upper: [utxoId], + includeUpper: include, + )); + }); + } + + QueryBuilder + utxoIdBetween( + int lowerUtxoId, + int upperUtxoId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'utxoId', + lower: [lowerUtxoId], + includeLower: includeLower, + upper: [upperUtxoId], + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualTo(String walletId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId', + value: [walletId], + )); + }); + } + + QueryBuilder + walletIdNotEqualTo(String walletId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [], + upper: [walletId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [walletId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [walletId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId', + lower: [], + upper: [walletId], + includeUpper: false, + )); + } + }); + } +} + +extension SilentPaymentMetadataQueryFilter on QueryBuilder< + SilentPaymentMetadata, SilentPaymentMetadata, QFilterCondition> { + QueryBuilder idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder labelIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'label', + )); + }); + } + + QueryBuilder labelIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'label', + )); + }); + } + + QueryBuilder labelEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder labelGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder labelLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder labelBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'label', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder labelStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder labelEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'label', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder labelIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'label', + value: '', + )); + }); + } + + QueryBuilder labelIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'label', + value: '', + )); + }); + } + + QueryBuilder outputIndexEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'outputIndex', + value: value, + )); + }); + } + + QueryBuilder outputIndexGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'outputIndex', + value: value, + )); + }); + } + + QueryBuilder outputIndexLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'outputIndex', + value: value, + )); + }); + } + + QueryBuilder outputIndexBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'outputIndex', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder privKeyTweakEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder privKeyTweakGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder privKeyTweakLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder privKeyTweakBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'privKeyTweak', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder privKeyTweakStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder privKeyTweakEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'privKeyTweak', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder privKeyTweakIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'privKeyTweak', + value: '', + )); + }); + } + + QueryBuilder privKeyTweakIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'privKeyTweak', + value: '', + )); + }); + } + + QueryBuilder sharedSecretIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'sharedSecret', + )); + }); + } + + QueryBuilder sharedSecretIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'sharedSecret', + )); + }); + } + + QueryBuilder sharedSecretEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'sharedSecret', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder sharedSecretGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'sharedSecret', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder sharedSecretLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'sharedSecret', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder sharedSecretBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'sharedSecret', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder sharedSecretStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'sharedSecret', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder sharedSecretEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'sharedSecret', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + sharedSecretContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'sharedSecret', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + sharedSecretMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'sharedSecret', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder sharedSecretIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'sharedSecret', + value: '', + )); + }); + } + + QueryBuilder sharedSecretIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'sharedSecret', + value: '', + )); + }); + } + + QueryBuilder utxoIdEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'utxoId', + value: value, + )); + }); + } + + QueryBuilder utxoIdGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'utxoId', + value: value, + )); + }); + } + + QueryBuilder utxoIdLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'utxoId', + value: value, + )); + }); + } + + QueryBuilder utxoIdBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'utxoId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder walletIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder walletIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder walletIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder walletIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'walletId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder walletIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder walletIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'walletId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder walletIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: '', + )); + }); + } + + QueryBuilder walletIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'walletId', + value: '', + )); + }); + } +} + +extension SilentPaymentMetadataQueryObject on QueryBuilder< + SilentPaymentMetadata, SilentPaymentMetadata, QFilterCondition> {} + +extension SilentPaymentMetadataQueryLinks on QueryBuilder {} + +extension SilentPaymentMetadataQuerySortBy + on QueryBuilder { + QueryBuilder + sortByLabel() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.asc); + }); + } + + QueryBuilder + sortByLabelDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.desc); + }); + } + + QueryBuilder + sortByOutputIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputIndex', Sort.asc); + }); + } + + QueryBuilder + sortByOutputIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputIndex', Sort.desc); + }); + } + + QueryBuilder + sortByPrivKeyTweak() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.asc); + }); + } + + QueryBuilder + sortByPrivKeyTweakDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.desc); + }); + } + + QueryBuilder + sortBySharedSecret() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedSecret', Sort.asc); + }); + } + + QueryBuilder + sortBySharedSecretDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedSecret', Sort.desc); + }); + } + + QueryBuilder + sortByUtxoId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'utxoId', Sort.asc); + }); + } + + QueryBuilder + sortByUtxoIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'utxoId', Sort.desc); + }); + } + + QueryBuilder + sortByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + sortByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentMetadataQuerySortThenBy + on QueryBuilder { + QueryBuilder + thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByLabel() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.asc); + }); + } + + QueryBuilder + thenByLabelDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.desc); + }); + } + + QueryBuilder + thenByOutputIndex() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputIndex', Sort.asc); + }); + } + + QueryBuilder + thenByOutputIndexDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputIndex', Sort.desc); + }); + } + + QueryBuilder + thenByPrivKeyTweak() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.asc); + }); + } + + QueryBuilder + thenByPrivKeyTweakDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.desc); + }); + } + + QueryBuilder + thenBySharedSecret() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedSecret', Sort.asc); + }); + } + + QueryBuilder + thenBySharedSecretDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sharedSecret', Sort.desc); + }); + } + + QueryBuilder + thenByUtxoId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'utxoId', Sort.asc); + }); + } + + QueryBuilder + thenByUtxoIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'utxoId', Sort.desc); + }); + } + + QueryBuilder + thenByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + thenByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentMetadataQueryWhereDistinct + on QueryBuilder { + QueryBuilder + distinctByLabel({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'label', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByOutputIndex() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'outputIndex'); + }); + } + + QueryBuilder + distinctByPrivKeyTweak({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'privKeyTweak', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctBySharedSecret({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'sharedSecret', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByUtxoId() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'utxoId'); + }); + } + + QueryBuilder + distinctByWalletId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); + }); + } +} + +extension SilentPaymentMetadataQueryProperty on QueryBuilder< + SilentPaymentMetadata, SilentPaymentMetadata, QQueryProperty> { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + labelProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'label'); + }); + } + + QueryBuilder + outputIndexProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'outputIndex'); + }); + } + + QueryBuilder + privKeyTweakProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'privKeyTweak'); + }); + } + + QueryBuilder + sharedSecretProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'sharedSecret'); + }); + } + + QueryBuilder utxoIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'utxoId'); + }); + } + + QueryBuilder + walletIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'walletId'); + }); + } +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_output.dart b/lib/models/isar/models/silent_payments/silent_payment_output.dart new file mode 100644 index 000000000..96259f976 --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_output.dart @@ -0,0 +1,172 @@ +// NOTE: might delete later to use metadata instead + +import 'package:isar/isar.dart'; +import '../../../../wallets/isar/isar_id_interface.dart'; + +part 'silent_payment_output.g.dart'; + +@Collection(accessor: "silentPaymentOutputs", inheritance: false) +class SilentPaymentOutput implements IsarId { + @override + Id id = Isar.autoIncrement; + + @Index(composite: [CompositeIndex('outputScript')]) + final String walletId; + + // The actual output script + final String outputScript; + + // Amount in satoshis + final int amount; + + // Transaction data + final String txid; + final int vout; + + // Block data + final int blockHeight; + final int blockTime; + + // Private key tweak needed to spend this output + final String privKeyTweak; + + // Optional label + final String? label; + + // Is this output spent + final bool isSpent; + + // Additional fields that might be useful + final String? spentTxid; // Transaction ID where this output was spent + final int? spentBlockHeight; // Block height when it was spent + final int? spentBlockTime; // Block timestamp when it was spent + + SilentPaymentOutput({ + required this.walletId, + required this.outputScript, + required this.amount, + required this.txid, + required this.vout, + required this.blockHeight, + required this.blockTime, + required this.privKeyTweak, + this.label, + this.isSpent = false, + this.spentTxid, + this.spentBlockHeight, + this.spentBlockTime, + }); + + // Copy with method for immutability + SilentPaymentOutput copyWith({ + String? walletId, + String? outputScript, + int? amount, + String? txid, + int? vout, + int? blockHeight, + int? blockTime, + String? privKeyTweak, + String? label, + bool? isSpent, + String? spentTxid, + int? spentBlockHeight, + int? spentBlockTime, + }) { + return SilentPaymentOutput( + walletId: walletId ?? this.walletId, + outputScript: outputScript ?? this.outputScript, + amount: amount ?? this.amount, + txid: txid ?? this.txid, + vout: vout ?? this.vout, + blockHeight: blockHeight ?? this.blockHeight, + blockTime: blockTime ?? this.blockTime, + privKeyTweak: privKeyTweak ?? this.privKeyTweak, + label: label ?? this.label, + isSpent: isSpent ?? this.isSpent, + spentTxid: spentTxid ?? this.spentTxid, + spentBlockHeight: spentBlockHeight ?? this.spentBlockHeight, + spentBlockTime: spentBlockTime ?? this.spentBlockTime, + )..id = id; + } + + // Mark this output as spent + Future markAsSpent({ + required Isar isar, + required String spentInTxid, + required int spentAtHeight, + required int spentAtTime, + }) async { + final thisOutput = await isar.silentPaymentOutputs.get(id) ?? this; + + // Only update if not already marked as spent + if (!thisOutput.isSpent) { + await isar.writeTxn(() async { + await isar.silentPaymentOutputs.delete(thisOutput.id); + await isar.silentPaymentOutputs.put( + thisOutput.copyWith( + isSpent: true, + spentTxid: spentInTxid, + spentBlockHeight: spentAtHeight, + spentBlockTime: spentAtTime, + ), + ); + }); + } + } + + // Update the label of this output + Future updateLabel({ + required Isar isar, + required String? newLabel, + }) async { + final thisOutput = await isar.silentPaymentOutputs.get(id) ?? this; + + // Only update if label is different + if (thisOutput.label != newLabel) { + await isar.writeTxn(() async { + await isar.silentPaymentOutputs.delete(thisOutput.id); + await isar.silentPaymentOutputs.put( + thisOutput.copyWith(label: newLabel), + ); + }); + } + } + + // Check if this output matches a specific UTXO/outpoint + bool matchesOutpoint(String checkTxid, int checkVout) { + return txid == checkTxid && vout == checkVout; + } + + // For convenience, create an outpoint string representation + String get outpoint => "$txid:$vout"; + + // Method to help calculate the effective age of the UTXO + int get confirmations { + // This would typically need the current block height, + // so you might pass that in as a parameter + final currentHeight = 0; // Replace with actual height + return currentHeight - blockHeight + 1; + } + + // Convenience getter for age in days (approximation) + double get ageInDays { + final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + return (now - blockTime) / (60 * 60 * 24); + } + + // Helper to detect if this output has been spent for a certain time + bool get isConfirmedSpent { + if (!isSpent || spentBlockHeight == null) return false; + + final currentHeight = 0; // Replace with actual height + // Consider spent outputs confirmed after 6 blocks + return currentHeight - spentBlockHeight! >= 6; + } + + // For debugging or display purposes + @override + String toString() { + return 'SilentPaymentOutput(id: $id, txid: $txid:$vout, amount: $amount sats, spent: $isSpent)'; + } +} diff --git a/lib/models/isar/models/silent_payments/silent_payment_output.g.dart b/lib/models/isar/models/silent_payments/silent_payment_output.g.dart new file mode 100644 index 000000000..ee9e673c5 --- /dev/null +++ b/lib/models/isar/models/silent_payments/silent_payment_output.g.dart @@ -0,0 +1,2752 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'silent_payment_output.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetSilentPaymentOutputCollection on Isar { + IsarCollection get silentPaymentOutputs => + this.collection(); +} + +const SilentPaymentOutputSchema = CollectionSchema( + name: r'SilentPaymentOutput', + id: 7199689495392272388, + properties: { + r'ageInDays': PropertySchema( + id: 0, + name: r'ageInDays', + type: IsarType.double, + ), + r'amount': PropertySchema( + id: 1, + name: r'amount', + type: IsarType.long, + ), + r'blockHeight': PropertySchema( + id: 2, + name: r'blockHeight', + type: IsarType.long, + ), + r'blockTime': PropertySchema( + id: 3, + name: r'blockTime', + type: IsarType.long, + ), + r'confirmations': PropertySchema( + id: 4, + name: r'confirmations', + type: IsarType.long, + ), + r'isConfirmedSpent': PropertySchema( + id: 5, + name: r'isConfirmedSpent', + type: IsarType.bool, + ), + r'isSpent': PropertySchema( + id: 6, + name: r'isSpent', + type: IsarType.bool, + ), + r'label': PropertySchema( + id: 7, + name: r'label', + type: IsarType.string, + ), + r'outpoint': PropertySchema( + id: 8, + name: r'outpoint', + type: IsarType.string, + ), + r'outputScript': PropertySchema( + id: 9, + name: r'outputScript', + type: IsarType.string, + ), + r'privKeyTweak': PropertySchema( + id: 10, + name: r'privKeyTweak', + type: IsarType.string, + ), + r'spentBlockHeight': PropertySchema( + id: 11, + name: r'spentBlockHeight', + type: IsarType.long, + ), + r'spentBlockTime': PropertySchema( + id: 12, + name: r'spentBlockTime', + type: IsarType.long, + ), + r'spentTxid': PropertySchema( + id: 13, + name: r'spentTxid', + type: IsarType.string, + ), + r'txid': PropertySchema( + id: 14, + name: r'txid', + type: IsarType.string, + ), + r'vout': PropertySchema( + id: 15, + name: r'vout', + type: IsarType.long, + ), + r'walletId': PropertySchema( + id: 16, + name: r'walletId', + type: IsarType.string, + ) + }, + estimateSize: _silentPaymentOutputEstimateSize, + serialize: _silentPaymentOutputSerialize, + deserialize: _silentPaymentOutputDeserialize, + deserializeProp: _silentPaymentOutputDeserializeProp, + idName: r'id', + indexes: { + r'walletId_outputScript': IndexSchema( + id: -4581886294710132914, + name: r'walletId_outputScript', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'walletId', + type: IndexType.hash, + caseSensitive: true, + ), + IndexPropertySchema( + name: r'outputScript', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _silentPaymentOutputGetId, + getLinks: _silentPaymentOutputGetLinks, + attach: _silentPaymentOutputAttach, + version: '3.1.8', +); + +int _silentPaymentOutputEstimateSize( + SilentPaymentOutput object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.label; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.outpoint.length * 3; + bytesCount += 3 + object.outputScript.length * 3; + bytesCount += 3 + object.privKeyTweak.length * 3; + { + final value = object.spentTxid; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + bytesCount += 3 + object.txid.length * 3; + bytesCount += 3 + object.walletId.length * 3; + return bytesCount; +} + +void _silentPaymentOutputSerialize( + SilentPaymentOutput object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeDouble(offsets[0], object.ageInDays); + writer.writeLong(offsets[1], object.amount); + writer.writeLong(offsets[2], object.blockHeight); + writer.writeLong(offsets[3], object.blockTime); + writer.writeLong(offsets[4], object.confirmations); + writer.writeBool(offsets[5], object.isConfirmedSpent); + writer.writeBool(offsets[6], object.isSpent); + writer.writeString(offsets[7], object.label); + writer.writeString(offsets[8], object.outpoint); + writer.writeString(offsets[9], object.outputScript); + writer.writeString(offsets[10], object.privKeyTweak); + writer.writeLong(offsets[11], object.spentBlockHeight); + writer.writeLong(offsets[12], object.spentBlockTime); + writer.writeString(offsets[13], object.spentTxid); + writer.writeString(offsets[14], object.txid); + writer.writeLong(offsets[15], object.vout); + writer.writeString(offsets[16], object.walletId); +} + +SilentPaymentOutput _silentPaymentOutputDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = SilentPaymentOutput( + amount: reader.readLong(offsets[1]), + blockHeight: reader.readLong(offsets[2]), + blockTime: reader.readLong(offsets[3]), + isSpent: reader.readBoolOrNull(offsets[6]) ?? false, + label: reader.readStringOrNull(offsets[7]), + outputScript: reader.readString(offsets[9]), + privKeyTweak: reader.readString(offsets[10]), + spentBlockHeight: reader.readLongOrNull(offsets[11]), + spentBlockTime: reader.readLongOrNull(offsets[12]), + spentTxid: reader.readStringOrNull(offsets[13]), + txid: reader.readString(offsets[14]), + vout: reader.readLong(offsets[15]), + walletId: reader.readString(offsets[16]), + ); + object.id = id; + return object; +} + +P _silentPaymentOutputDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readDouble(offset)) as P; + case 1: + return (reader.readLong(offset)) as P; + case 2: + return (reader.readLong(offset)) as P; + case 3: + return (reader.readLong(offset)) as P; + case 4: + return (reader.readLong(offset)) as P; + case 5: + return (reader.readBool(offset)) as P; + case 6: + return (reader.readBoolOrNull(offset) ?? false) as P; + case 7: + return (reader.readStringOrNull(offset)) as P; + case 8: + return (reader.readString(offset)) as P; + case 9: + return (reader.readString(offset)) as P; + case 10: + return (reader.readString(offset)) as P; + case 11: + return (reader.readLongOrNull(offset)) as P; + case 12: + return (reader.readLongOrNull(offset)) as P; + case 13: + return (reader.readStringOrNull(offset)) as P; + case 14: + return (reader.readString(offset)) as P; + case 15: + return (reader.readLong(offset)) as P; + case 16: + return (reader.readString(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _silentPaymentOutputGetId(SilentPaymentOutput object) { + return object.id; +} + +List> _silentPaymentOutputGetLinks( + SilentPaymentOutput object) { + return []; +} + +void _silentPaymentOutputAttach( + IsarCollection col, Id id, SilentPaymentOutput object) { + object.id = id; +} + +extension SilentPaymentOutputQueryWhereSort + on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension SilentPaymentOutputQueryWhere + on QueryBuilder { + QueryBuilder + idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder + idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder + idGreaterThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder + idLessThan(Id id, {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder + idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualToAnyOutputScript(String walletId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId_outputScript', + value: [walletId], + )); + }); + } + + QueryBuilder + walletIdNotEqualToAnyOutputScript(String walletId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [], + upper: [walletId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [walletId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [walletId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [], + upper: [walletId], + includeUpper: false, + )); + } + }); + } + + QueryBuilder + walletIdOutputScriptEqualTo(String walletId, String outputScript) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'walletId_outputScript', + value: [walletId, outputScript], + )); + }); + } + + QueryBuilder + walletIdEqualToOutputScriptNotEqualTo( + String walletId, String outputScript) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [walletId], + upper: [walletId, outputScript], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [walletId, outputScript], + includeLower: false, + upper: [walletId], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [walletId, outputScript], + includeLower: false, + upper: [walletId], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'walletId_outputScript', + lower: [walletId], + upper: [walletId, outputScript], + includeUpper: false, + )); + } + }); + } +} + +extension SilentPaymentOutputQueryFilter on QueryBuilder { + QueryBuilder + ageInDaysEqualTo( + double value, { + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'ageInDays', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder + ageInDaysGreaterThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'ageInDays', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder + ageInDaysLessThan( + double value, { + bool include = false, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'ageInDays', + value: value, + epsilon: epsilon, + )); + }); + } + + QueryBuilder + ageInDaysBetween( + double lower, + double upper, { + bool includeLower = true, + bool includeUpper = true, + double epsilon = Query.epsilon, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'ageInDays', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + epsilon: epsilon, + )); + }); + } + + QueryBuilder + amountEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'amount', + value: value, + )); + }); + } + + QueryBuilder + amountGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'amount', + value: value, + )); + }); + } + + QueryBuilder + amountLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'amount', + value: value, + )); + }); + } + + QueryBuilder + amountBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'amount', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + blockHeightEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'blockHeight', + value: value, + )); + }); + } + + QueryBuilder + blockHeightGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'blockHeight', + value: value, + )); + }); + } + + QueryBuilder + blockHeightLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'blockHeight', + value: value, + )); + }); + } + + QueryBuilder + blockHeightBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'blockHeight', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + blockTimeEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'blockTime', + value: value, + )); + }); + } + + QueryBuilder + blockTimeGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'blockTime', + value: value, + )); + }); + } + + QueryBuilder + blockTimeLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'blockTime', + value: value, + )); + }); + } + + QueryBuilder + blockTimeBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'blockTime', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + confirmationsEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'confirmations', + value: value, + )); + }); + } + + QueryBuilder + confirmationsGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'confirmations', + value: value, + )); + }); + } + + QueryBuilder + confirmationsLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'confirmations', + value: value, + )); + }); + } + + QueryBuilder + confirmationsBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'confirmations', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder + idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + isConfirmedSpentEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isConfirmedSpent', + value: value, + )); + }); + } + + QueryBuilder + isSpentEqualTo(bool value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'isSpent', + value: value, + )); + }); + } + + QueryBuilder + labelIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'label', + )); + }); + } + + QueryBuilder + labelIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'label', + )); + }); + } + + QueryBuilder + labelEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'label', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'label', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'label', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + labelIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'label', + value: '', + )); + }); + } + + QueryBuilder + labelIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'label', + value: '', + )); + }); + } + + QueryBuilder + outpointEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'outpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'outpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'outpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'outpoint', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'outpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'outpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'outpoint', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'outpoint', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outpointIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'outpoint', + value: '', + )); + }); + } + + QueryBuilder + outpointIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'outpoint', + value: '', + )); + }); + } + + QueryBuilder + outputScriptEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'outputScript', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'outputScript', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'outputScript', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'outputScript', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'outputScript', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'outputScript', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'outputScript', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'outputScript', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + outputScriptIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'outputScript', + value: '', + )); + }); + } + + QueryBuilder + outputScriptIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'outputScript', + value: '', + )); + }); + } + + QueryBuilder + privKeyTweakEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'privKeyTweak', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'privKeyTweak', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'privKeyTweak', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + privKeyTweakIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'privKeyTweak', + value: '', + )); + }); + } + + QueryBuilder + privKeyTweakIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'privKeyTweak', + value: '', + )); + }); + } + + QueryBuilder + spentBlockHeightIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'spentBlockHeight', + )); + }); + } + + QueryBuilder + spentBlockHeightIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'spentBlockHeight', + )); + }); + } + + QueryBuilder + spentBlockHeightEqualTo(int? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'spentBlockHeight', + value: value, + )); + }); + } + + QueryBuilder + spentBlockHeightGreaterThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'spentBlockHeight', + value: value, + )); + }); + } + + QueryBuilder + spentBlockHeightLessThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'spentBlockHeight', + value: value, + )); + }); + } + + QueryBuilder + spentBlockHeightBetween( + int? lower, + int? upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'spentBlockHeight', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + spentBlockTimeIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'spentBlockTime', + )); + }); + } + + QueryBuilder + spentBlockTimeIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'spentBlockTime', + )); + }); + } + + QueryBuilder + spentBlockTimeEqualTo(int? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'spentBlockTime', + value: value, + )); + }); + } + + QueryBuilder + spentBlockTimeGreaterThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'spentBlockTime', + value: value, + )); + }); + } + + QueryBuilder + spentBlockTimeLessThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'spentBlockTime', + value: value, + )); + }); + } + + QueryBuilder + spentBlockTimeBetween( + int? lower, + int? upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'spentBlockTime', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + spentTxidIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'spentTxid', + )); + }); + } + + QueryBuilder + spentTxidIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'spentTxid', + )); + }); + } + + QueryBuilder + spentTxidEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'spentTxid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'spentTxid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'spentTxid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'spentTxid', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'spentTxid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'spentTxid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'spentTxid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'spentTxid', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + spentTxidIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'spentTxid', + value: '', + )); + }); + } + + QueryBuilder + spentTxidIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'spentTxid', + value: '', + )); + }); + } + + QueryBuilder + txidEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'txid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'txid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'txid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'txid', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'txid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'txid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'txid', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'txid', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + txidIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'txid', + value: '', + )); + }); + } + + QueryBuilder + txidIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'txid', + value: '', + )); + }); + } + + QueryBuilder + voutEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'vout', + value: value, + )); + }); + } + + QueryBuilder + voutGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'vout', + value: value, + )); + }); + } + + QueryBuilder + voutLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'vout', + value: value, + )); + }); + } + + QueryBuilder + voutBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'vout', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + walletIdEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'walletId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'walletId', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'walletId', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + walletIdIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'walletId', + value: '', + )); + }); + } + + QueryBuilder + walletIdIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'walletId', + value: '', + )); + }); + } +} + +extension SilentPaymentOutputQueryObject on QueryBuilder {} + +extension SilentPaymentOutputQueryLinks on QueryBuilder {} + +extension SilentPaymentOutputQuerySortBy + on QueryBuilder { + QueryBuilder + sortByAgeInDays() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'ageInDays', Sort.asc); + }); + } + + QueryBuilder + sortByAgeInDaysDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'ageInDays', Sort.desc); + }); + } + + QueryBuilder + sortByAmount() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'amount', Sort.asc); + }); + } + + QueryBuilder + sortByAmountDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'amount', Sort.desc); + }); + } + + QueryBuilder + sortByBlockHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockHeight', Sort.asc); + }); + } + + QueryBuilder + sortByBlockHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockHeight', Sort.desc); + }); + } + + QueryBuilder + sortByBlockTime() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockTime', Sort.asc); + }); + } + + QueryBuilder + sortByBlockTimeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockTime', Sort.desc); + }); + } + + QueryBuilder + sortByConfirmations() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'confirmations', Sort.asc); + }); + } + + QueryBuilder + sortByConfirmationsDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'confirmations', Sort.desc); + }); + } + + QueryBuilder + sortByIsConfirmedSpent() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isConfirmedSpent', Sort.asc); + }); + } + + QueryBuilder + sortByIsConfirmedSpentDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isConfirmedSpent', Sort.desc); + }); + } + + QueryBuilder + sortByIsSpent() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isSpent', Sort.asc); + }); + } + + QueryBuilder + sortByIsSpentDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isSpent', Sort.desc); + }); + } + + QueryBuilder + sortByLabel() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.asc); + }); + } + + QueryBuilder + sortByLabelDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.desc); + }); + } + + QueryBuilder + sortByOutpoint() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outpoint', Sort.asc); + }); + } + + QueryBuilder + sortByOutpointDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outpoint', Sort.desc); + }); + } + + QueryBuilder + sortByOutputScript() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputScript', Sort.asc); + }); + } + + QueryBuilder + sortByOutputScriptDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputScript', Sort.desc); + }); + } + + QueryBuilder + sortByPrivKeyTweak() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.asc); + }); + } + + QueryBuilder + sortByPrivKeyTweakDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.desc); + }); + } + + QueryBuilder + sortBySpentBlockHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockHeight', Sort.asc); + }); + } + + QueryBuilder + sortBySpentBlockHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockHeight', Sort.desc); + }); + } + + QueryBuilder + sortBySpentBlockTime() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockTime', Sort.asc); + }); + } + + QueryBuilder + sortBySpentBlockTimeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockTime', Sort.desc); + }); + } + + QueryBuilder + sortBySpentTxid() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentTxid', Sort.asc); + }); + } + + QueryBuilder + sortBySpentTxidDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentTxid', Sort.desc); + }); + } + + QueryBuilder + sortByTxid() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'txid', Sort.asc); + }); + } + + QueryBuilder + sortByTxidDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'txid', Sort.desc); + }); + } + + QueryBuilder + sortByVout() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'vout', Sort.asc); + }); + } + + QueryBuilder + sortByVoutDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'vout', Sort.desc); + }); + } + + QueryBuilder + sortByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + sortByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentOutputQuerySortThenBy + on QueryBuilder { + QueryBuilder + thenByAgeInDays() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'ageInDays', Sort.asc); + }); + } + + QueryBuilder + thenByAgeInDaysDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'ageInDays', Sort.desc); + }); + } + + QueryBuilder + thenByAmount() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'amount', Sort.asc); + }); + } + + QueryBuilder + thenByAmountDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'amount', Sort.desc); + }); + } + + QueryBuilder + thenByBlockHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockHeight', Sort.asc); + }); + } + + QueryBuilder + thenByBlockHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockHeight', Sort.desc); + }); + } + + QueryBuilder + thenByBlockTime() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockTime', Sort.asc); + }); + } + + QueryBuilder + thenByBlockTimeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'blockTime', Sort.desc); + }); + } + + QueryBuilder + thenByConfirmations() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'confirmations', Sort.asc); + }); + } + + QueryBuilder + thenByConfirmationsDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'confirmations', Sort.desc); + }); + } + + QueryBuilder + thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder + thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder + thenByIsConfirmedSpent() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isConfirmedSpent', Sort.asc); + }); + } + + QueryBuilder + thenByIsConfirmedSpentDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isConfirmedSpent', Sort.desc); + }); + } + + QueryBuilder + thenByIsSpent() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isSpent', Sort.asc); + }); + } + + QueryBuilder + thenByIsSpentDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'isSpent', Sort.desc); + }); + } + + QueryBuilder + thenByLabel() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.asc); + }); + } + + QueryBuilder + thenByLabelDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'label', Sort.desc); + }); + } + + QueryBuilder + thenByOutpoint() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outpoint', Sort.asc); + }); + } + + QueryBuilder + thenByOutpointDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outpoint', Sort.desc); + }); + } + + QueryBuilder + thenByOutputScript() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputScript', Sort.asc); + }); + } + + QueryBuilder + thenByOutputScriptDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'outputScript', Sort.desc); + }); + } + + QueryBuilder + thenByPrivKeyTweak() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.asc); + }); + } + + QueryBuilder + thenByPrivKeyTweakDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'privKeyTweak', Sort.desc); + }); + } + + QueryBuilder + thenBySpentBlockHeight() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockHeight', Sort.asc); + }); + } + + QueryBuilder + thenBySpentBlockHeightDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockHeight', Sort.desc); + }); + } + + QueryBuilder + thenBySpentBlockTime() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockTime', Sort.asc); + }); + } + + QueryBuilder + thenBySpentBlockTimeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentBlockTime', Sort.desc); + }); + } + + QueryBuilder + thenBySpentTxid() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentTxid', Sort.asc); + }); + } + + QueryBuilder + thenBySpentTxidDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'spentTxid', Sort.desc); + }); + } + + QueryBuilder + thenByTxid() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'txid', Sort.asc); + }); + } + + QueryBuilder + thenByTxidDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'txid', Sort.desc); + }); + } + + QueryBuilder + thenByVout() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'vout', Sort.asc); + }); + } + + QueryBuilder + thenByVoutDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'vout', Sort.desc); + }); + } + + QueryBuilder + thenByWalletId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.asc); + }); + } + + QueryBuilder + thenByWalletIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'walletId', Sort.desc); + }); + } +} + +extension SilentPaymentOutputQueryWhereDistinct + on QueryBuilder { + QueryBuilder + distinctByAgeInDays() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'ageInDays'); + }); + } + + QueryBuilder + distinctByAmount() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'amount'); + }); + } + + QueryBuilder + distinctByBlockHeight() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'blockHeight'); + }); + } + + QueryBuilder + distinctByBlockTime() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'blockTime'); + }); + } + + QueryBuilder + distinctByConfirmations() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'confirmations'); + }); + } + + QueryBuilder + distinctByIsConfirmedSpent() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isConfirmedSpent'); + }); + } + + QueryBuilder + distinctByIsSpent() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'isSpent'); + }); + } + + QueryBuilder + distinctByLabel({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'label', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByOutpoint({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'outpoint', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByOutputScript({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'outputScript', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByPrivKeyTweak({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'privKeyTweak', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctBySpentBlockHeight() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'spentBlockHeight'); + }); + } + + QueryBuilder + distinctBySpentBlockTime() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'spentBlockTime'); + }); + } + + QueryBuilder + distinctBySpentTxid({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'spentTxid', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByTxid({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'txid', caseSensitive: caseSensitive); + }); + } + + QueryBuilder + distinctByVout() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'vout'); + }); + } + + QueryBuilder + distinctByWalletId({bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); + }); + } +} + +extension SilentPaymentOutputQueryProperty + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + ageInDaysProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'ageInDays'); + }); + } + + QueryBuilder amountProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'amount'); + }); + } + + QueryBuilder + blockHeightProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'blockHeight'); + }); + } + + QueryBuilder blockTimeProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'blockTime'); + }); + } + + QueryBuilder + confirmationsProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'confirmations'); + }); + } + + QueryBuilder + isConfirmedSpentProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isConfirmedSpent'); + }); + } + + QueryBuilder isSpentProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'isSpent'); + }); + } + + QueryBuilder labelProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'label'); + }); + } + + QueryBuilder + outpointProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'outpoint'); + }); + } + + QueryBuilder + outputScriptProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'outputScript'); + }); + } + + QueryBuilder + privKeyTweakProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'privKeyTweak'); + }); + } + + QueryBuilder + spentBlockHeightProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'spentBlockHeight'); + }); + } + + QueryBuilder + spentBlockTimeProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'spentBlockTime'); + }); + } + + QueryBuilder + spentTxidProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'spentTxid'); + }); + } + + QueryBuilder txidProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'txid'); + }); + } + + QueryBuilder voutProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'vout'); + }); + } + + QueryBuilder + walletIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'walletId'); + }); + } +} From 8165dac624e6ce69609b87d5113974b9a2f94caa Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Sun, 27 Apr 2025 21:06:11 -0400 Subject: [PATCH 09/14] delete unwanted models --- .../silent_payments/silent_payment_data.dart | 76 - .../silent_payment_data.g.dart | 945 ------ .../silent_payment_output.dart | 172 -- .../silent_payment_output.g.dart | 2752 ----------------- 4 files changed, 3945 deletions(-) delete mode 100644 lib/models/isar/models/silent_payments/silent_payment_data.dart delete mode 100644 lib/models/isar/models/silent_payments/silent_payment_data.g.dart delete mode 100644 lib/models/isar/models/silent_payments/silent_payment_output.dart delete mode 100644 lib/models/isar/models/silent_payments/silent_payment_output.g.dart diff --git a/lib/models/isar/models/silent_payments/silent_payment_data.dart b/lib/models/isar/models/silent_payments/silent_payment_data.dart deleted file mode 100644 index f650991be..000000000 --- a/lib/models/isar/models/silent_payments/silent_payment_data.dart +++ /dev/null @@ -1,76 +0,0 @@ -// NOTE: might delete later to use config instead - -import 'dart:convert'; - -import 'package:isar/isar.dart'; -import '../../../../wallets/isar/isar_id_interface.dart'; - -part 'silent_payment_data.g.dart'; - -@Collection(accessor: "silentPaymentData", inheritance: false) -class SilentPaymentData implements IsarId { - @override - Id id = Isar.autoIncrement; - - @Index(unique: true, replace: false) - final String walletId; - - // Whether this wallet has silent payments scanning enabled - final bool isEnabled; - - // The last block height scanned for silent payments - final int lastScannedHeight; - - // Store any additional data as JSON - final String? metadataJsonString; - - // Convenience getters - @ignore - Map get metadata => - metadataJsonString == null - ? {} - : Map.from(jsonDecode(metadataJsonString!) as Map); - - SilentPaymentData({ - required this.walletId, - this.isEnabled = false, - this.lastScannedHeight = 0, - this.metadataJsonString, - }); - - // Modification methods - SilentPaymentData copyWith({ - bool? isEnabled, - int? lastScannedHeight, - String? metadataJsonString, - }) { - return SilentPaymentData( - walletId: walletId, - isEnabled: isEnabled ?? this.isEnabled, - lastScannedHeight: lastScannedHeight ?? this.lastScannedHeight, - metadataJsonString: metadataJsonString ?? this.metadataJsonString, - )..id = id; - } - - // Database update methods - Future updateEnabled({ - required bool enabled, - required Isar isar, - }) async { - final data = - await isar.silentPaymentData - .where() - .walletIdEqualTo(walletId) - .findFirst() ?? - this; - - if (data.isEnabled != enabled) { - await isar.writeTxn(() async { - await isar.silentPaymentData.delete(data.id); - await isar.silentPaymentData.put(data.copyWith(isEnabled: enabled)); - }); - } - } - - // Similar methods for updating lastScannedHeight, etc. -} diff --git a/lib/models/isar/models/silent_payments/silent_payment_data.g.dart b/lib/models/isar/models/silent_payments/silent_payment_data.g.dart deleted file mode 100644 index 7a468e0eb..000000000 --- a/lib/models/isar/models/silent_payments/silent_payment_data.g.dart +++ /dev/null @@ -1,945 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'silent_payment_data.dart'; - -// ************************************************************************** -// IsarCollectionGenerator -// ************************************************************************** - -// coverage:ignore-file -// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types - -extension GetSilentPaymentDataCollection on Isar { - IsarCollection get silentPaymentData => this.collection(); -} - -const SilentPaymentDataSchema = CollectionSchema( - name: r'SilentPaymentData', - id: -2677381250855078109, - properties: { - r'isEnabled': PropertySchema( - id: 0, - name: r'isEnabled', - type: IsarType.bool, - ), - r'lastScannedHeight': PropertySchema( - id: 1, - name: r'lastScannedHeight', - type: IsarType.long, - ), - r'metadataJsonString': PropertySchema( - id: 2, - name: r'metadataJsonString', - type: IsarType.string, - ), - r'walletId': PropertySchema( - id: 3, - name: r'walletId', - type: IsarType.string, - ) - }, - estimateSize: _silentPaymentDataEstimateSize, - serialize: _silentPaymentDataSerialize, - deserialize: _silentPaymentDataDeserialize, - deserializeProp: _silentPaymentDataDeserializeProp, - idName: r'id', - indexes: { - r'walletId': IndexSchema( - id: -1783113319798776304, - name: r'walletId', - unique: true, - replace: false, - properties: [ - IndexPropertySchema( - name: r'walletId', - type: IndexType.hash, - caseSensitive: true, - ) - ], - ) - }, - links: {}, - embeddedSchemas: {}, - getId: _silentPaymentDataGetId, - getLinks: _silentPaymentDataGetLinks, - attach: _silentPaymentDataAttach, - version: '3.1.8', -); - -int _silentPaymentDataEstimateSize( - SilentPaymentData object, - List offsets, - Map> allOffsets, -) { - var bytesCount = offsets.last; - { - final value = object.metadataJsonString; - if (value != null) { - bytesCount += 3 + value.length * 3; - } - } - bytesCount += 3 + object.walletId.length * 3; - return bytesCount; -} - -void _silentPaymentDataSerialize( - SilentPaymentData object, - IsarWriter writer, - List offsets, - Map> allOffsets, -) { - writer.writeBool(offsets[0], object.isEnabled); - writer.writeLong(offsets[1], object.lastScannedHeight); - writer.writeString(offsets[2], object.metadataJsonString); - writer.writeString(offsets[3], object.walletId); -} - -SilentPaymentData _silentPaymentDataDeserialize( - Id id, - IsarReader reader, - List offsets, - Map> allOffsets, -) { - final object = SilentPaymentData( - isEnabled: reader.readBoolOrNull(offsets[0]) ?? false, - lastScannedHeight: reader.readLongOrNull(offsets[1]) ?? 0, - metadataJsonString: reader.readStringOrNull(offsets[2]), - walletId: reader.readString(offsets[3]), - ); - object.id = id; - return object; -} - -P _silentPaymentDataDeserializeProp

( - IsarReader reader, - int propertyId, - int offset, - Map> allOffsets, -) { - switch (propertyId) { - case 0: - return (reader.readBoolOrNull(offset) ?? false) as P; - case 1: - return (reader.readLongOrNull(offset) ?? 0) as P; - case 2: - return (reader.readStringOrNull(offset)) as P; - case 3: - return (reader.readString(offset)) as P; - default: - throw IsarError('Unknown property with id $propertyId'); - } -} - -Id _silentPaymentDataGetId(SilentPaymentData object) { - return object.id; -} - -List> _silentPaymentDataGetLinks( - SilentPaymentData object) { - return []; -} - -void _silentPaymentDataAttach( - IsarCollection col, Id id, SilentPaymentData object) { - object.id = id; -} - -extension SilentPaymentDataByIndex on IsarCollection { - Future getByWalletId(String walletId) { - return getByIndex(r'walletId', [walletId]); - } - - SilentPaymentData? getByWalletIdSync(String walletId) { - return getByIndexSync(r'walletId', [walletId]); - } - - Future deleteByWalletId(String walletId) { - return deleteByIndex(r'walletId', [walletId]); - } - - bool deleteByWalletIdSync(String walletId) { - return deleteByIndexSync(r'walletId', [walletId]); - } - - Future> getAllByWalletId( - List walletIdValues) { - final values = walletIdValues.map((e) => [e]).toList(); - return getAllByIndex(r'walletId', values); - } - - List getAllByWalletIdSync(List walletIdValues) { - final values = walletIdValues.map((e) => [e]).toList(); - return getAllByIndexSync(r'walletId', values); - } - - Future deleteAllByWalletId(List walletIdValues) { - final values = walletIdValues.map((e) => [e]).toList(); - return deleteAllByIndex(r'walletId', values); - } - - int deleteAllByWalletIdSync(List walletIdValues) { - final values = walletIdValues.map((e) => [e]).toList(); - return deleteAllByIndexSync(r'walletId', values); - } - - Future putByWalletId(SilentPaymentData object) { - return putByIndex(r'walletId', object); - } - - Id putByWalletIdSync(SilentPaymentData object, {bool saveLinks = true}) { - return putByIndexSync(r'walletId', object, saveLinks: saveLinks); - } - - Future> putAllByWalletId(List objects) { - return putAllByIndex(r'walletId', objects); - } - - List putAllByWalletIdSync(List objects, - {bool saveLinks = true}) { - return putAllByIndexSync(r'walletId', objects, saveLinks: saveLinks); - } -} - -extension SilentPaymentDataQueryWhereSort - on QueryBuilder { - QueryBuilder anyId() { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(const IdWhereClause.any()); - }); - } -} - -extension SilentPaymentDataQueryWhere - on QueryBuilder { - QueryBuilder - idEqualTo(Id id) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IdWhereClause.between( - lower: id, - upper: id, - )); - }); - } - - QueryBuilder - idNotEqualTo(Id id) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: false), - ) - .addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: false), - ); - } else { - return query - .addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: false), - ) - .addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: false), - ); - } - }); - } - - QueryBuilder - idGreaterThan(Id id, {bool include = false}) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: include), - ); - }); - } - - QueryBuilder - idLessThan(Id id, {bool include = false}) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: include), - ); - }); - } - - QueryBuilder - idBetween( - Id lowerId, - Id upperId, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IdWhereClause.between( - lower: lowerId, - includeLower: includeLower, - upper: upperId, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - walletIdEqualTo(String walletId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'walletId', - value: [walletId], - )); - }); - } - - QueryBuilder - walletIdNotEqualTo(String walletId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [], - upper: [walletId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [walletId], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [walletId], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [], - upper: [walletId], - includeUpper: false, - )); - } - }); - } -} - -extension SilentPaymentDataQueryFilter - on QueryBuilder { - QueryBuilder - idEqualTo(Id value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'id', - value: value, - )); - }); - } - - QueryBuilder - idGreaterThan( - Id value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'id', - value: value, - )); - }); - } - - QueryBuilder - idLessThan( - Id value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'id', - value: value, - )); - }); - } - - QueryBuilder - idBetween( - Id lower, - Id upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'id', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - isEnabledEqualTo(bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isEnabled', - value: value, - )); - }); - } - - QueryBuilder - lastScannedHeightEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'lastScannedHeight', - value: value, - )); - }); - } - - QueryBuilder - lastScannedHeightGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'lastScannedHeight', - value: value, - )); - }); - } - - QueryBuilder - lastScannedHeightLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'lastScannedHeight', - value: value, - )); - }); - } - - QueryBuilder - lastScannedHeightBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'lastScannedHeight', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - metadataJsonStringIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'metadataJsonString', - )); - }); - } - - QueryBuilder - metadataJsonStringIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'metadataJsonString', - )); - }); - } - - QueryBuilder - metadataJsonStringEqualTo( - String? value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'metadataJsonString', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringGreaterThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'metadataJsonString', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringLessThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'metadataJsonString', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringBetween( - String? lower, - String? upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'metadataJsonString', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'metadataJsonString', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'metadataJsonString', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'metadataJsonString', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'metadataJsonString', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - metadataJsonStringIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'metadataJsonString', - value: '', - )); - }); - } - - QueryBuilder - metadataJsonStringIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'metadataJsonString', - value: '', - )); - }); - } - - QueryBuilder - walletIdEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'walletId', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'walletId', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: '', - )); - }); - } - - QueryBuilder - walletIdIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'walletId', - value: '', - )); - }); - } -} - -extension SilentPaymentDataQueryObject - on QueryBuilder {} - -extension SilentPaymentDataQueryLinks - on QueryBuilder {} - -extension SilentPaymentDataQuerySortBy - on QueryBuilder { - QueryBuilder - sortByIsEnabled() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isEnabled', Sort.asc); - }); - } - - QueryBuilder - sortByIsEnabledDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isEnabled', Sort.desc); - }); - } - - QueryBuilder - sortByLastScannedHeight() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'lastScannedHeight', Sort.asc); - }); - } - - QueryBuilder - sortByLastScannedHeightDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'lastScannedHeight', Sort.desc); - }); - } - - QueryBuilder - sortByMetadataJsonString() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'metadataJsonString', Sort.asc); - }); - } - - QueryBuilder - sortByMetadataJsonStringDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'metadataJsonString', Sort.desc); - }); - } - - QueryBuilder - sortByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder - sortByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension SilentPaymentDataQuerySortThenBy - on QueryBuilder { - QueryBuilder thenById() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.asc); - }); - } - - QueryBuilder - thenByIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.desc); - }); - } - - QueryBuilder - thenByIsEnabled() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isEnabled', Sort.asc); - }); - } - - QueryBuilder - thenByIsEnabledDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isEnabled', Sort.desc); - }); - } - - QueryBuilder - thenByLastScannedHeight() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'lastScannedHeight', Sort.asc); - }); - } - - QueryBuilder - thenByLastScannedHeightDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'lastScannedHeight', Sort.desc); - }); - } - - QueryBuilder - thenByMetadataJsonString() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'metadataJsonString', Sort.asc); - }); - } - - QueryBuilder - thenByMetadataJsonStringDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'metadataJsonString', Sort.desc); - }); - } - - QueryBuilder - thenByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder - thenByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension SilentPaymentDataQueryWhereDistinct - on QueryBuilder { - QueryBuilder - distinctByIsEnabled() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isEnabled'); - }); - } - - QueryBuilder - distinctByLastScannedHeight() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'lastScannedHeight'); - }); - } - - QueryBuilder - distinctByMetadataJsonString({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'metadataJsonString', - caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByWalletId({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); - }); - } -} - -extension SilentPaymentDataQueryProperty - on QueryBuilder { - QueryBuilder idProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'id'); - }); - } - - QueryBuilder isEnabledProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isEnabled'); - }); - } - - QueryBuilder - lastScannedHeightProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'lastScannedHeight'); - }); - } - - QueryBuilder - metadataJsonStringProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'metadataJsonString'); - }); - } - - QueryBuilder walletIdProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'walletId'); - }); - } -} diff --git a/lib/models/isar/models/silent_payments/silent_payment_output.dart b/lib/models/isar/models/silent_payments/silent_payment_output.dart deleted file mode 100644 index 96259f976..000000000 --- a/lib/models/isar/models/silent_payments/silent_payment_output.dart +++ /dev/null @@ -1,172 +0,0 @@ -// NOTE: might delete later to use metadata instead - -import 'package:isar/isar.dart'; -import '../../../../wallets/isar/isar_id_interface.dart'; - -part 'silent_payment_output.g.dart'; - -@Collection(accessor: "silentPaymentOutputs", inheritance: false) -class SilentPaymentOutput implements IsarId { - @override - Id id = Isar.autoIncrement; - - @Index(composite: [CompositeIndex('outputScript')]) - final String walletId; - - // The actual output script - final String outputScript; - - // Amount in satoshis - final int amount; - - // Transaction data - final String txid; - final int vout; - - // Block data - final int blockHeight; - final int blockTime; - - // Private key tweak needed to spend this output - final String privKeyTweak; - - // Optional label - final String? label; - - // Is this output spent - final bool isSpent; - - // Additional fields that might be useful - final String? spentTxid; // Transaction ID where this output was spent - final int? spentBlockHeight; // Block height when it was spent - final int? spentBlockTime; // Block timestamp when it was spent - - SilentPaymentOutput({ - required this.walletId, - required this.outputScript, - required this.amount, - required this.txid, - required this.vout, - required this.blockHeight, - required this.blockTime, - required this.privKeyTweak, - this.label, - this.isSpent = false, - this.spentTxid, - this.spentBlockHeight, - this.spentBlockTime, - }); - - // Copy with method for immutability - SilentPaymentOutput copyWith({ - String? walletId, - String? outputScript, - int? amount, - String? txid, - int? vout, - int? blockHeight, - int? blockTime, - String? privKeyTweak, - String? label, - bool? isSpent, - String? spentTxid, - int? spentBlockHeight, - int? spentBlockTime, - }) { - return SilentPaymentOutput( - walletId: walletId ?? this.walletId, - outputScript: outputScript ?? this.outputScript, - amount: amount ?? this.amount, - txid: txid ?? this.txid, - vout: vout ?? this.vout, - blockHeight: blockHeight ?? this.blockHeight, - blockTime: blockTime ?? this.blockTime, - privKeyTweak: privKeyTweak ?? this.privKeyTweak, - label: label ?? this.label, - isSpent: isSpent ?? this.isSpent, - spentTxid: spentTxid ?? this.spentTxid, - spentBlockHeight: spentBlockHeight ?? this.spentBlockHeight, - spentBlockTime: spentBlockTime ?? this.spentBlockTime, - )..id = id; - } - - // Mark this output as spent - Future markAsSpent({ - required Isar isar, - required String spentInTxid, - required int spentAtHeight, - required int spentAtTime, - }) async { - final thisOutput = await isar.silentPaymentOutputs.get(id) ?? this; - - // Only update if not already marked as spent - if (!thisOutput.isSpent) { - await isar.writeTxn(() async { - await isar.silentPaymentOutputs.delete(thisOutput.id); - await isar.silentPaymentOutputs.put( - thisOutput.copyWith( - isSpent: true, - spentTxid: spentInTxid, - spentBlockHeight: spentAtHeight, - spentBlockTime: spentAtTime, - ), - ); - }); - } - } - - // Update the label of this output - Future updateLabel({ - required Isar isar, - required String? newLabel, - }) async { - final thisOutput = await isar.silentPaymentOutputs.get(id) ?? this; - - // Only update if label is different - if (thisOutput.label != newLabel) { - await isar.writeTxn(() async { - await isar.silentPaymentOutputs.delete(thisOutput.id); - await isar.silentPaymentOutputs.put( - thisOutput.copyWith(label: newLabel), - ); - }); - } - } - - // Check if this output matches a specific UTXO/outpoint - bool matchesOutpoint(String checkTxid, int checkVout) { - return txid == checkTxid && vout == checkVout; - } - - // For convenience, create an outpoint string representation - String get outpoint => "$txid:$vout"; - - // Method to help calculate the effective age of the UTXO - int get confirmations { - // This would typically need the current block height, - // so you might pass that in as a parameter - final currentHeight = 0; // Replace with actual height - return currentHeight - blockHeight + 1; - } - - // Convenience getter for age in days (approximation) - double get ageInDays { - final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; - return (now - blockTime) / (60 * 60 * 24); - } - - // Helper to detect if this output has been spent for a certain time - bool get isConfirmedSpent { - if (!isSpent || spentBlockHeight == null) return false; - - final currentHeight = 0; // Replace with actual height - // Consider spent outputs confirmed after 6 blocks - return currentHeight - spentBlockHeight! >= 6; - } - - // For debugging or display purposes - @override - String toString() { - return 'SilentPaymentOutput(id: $id, txid: $txid:$vout, amount: $amount sats, spent: $isSpent)'; - } -} diff --git a/lib/models/isar/models/silent_payments/silent_payment_output.g.dart b/lib/models/isar/models/silent_payments/silent_payment_output.g.dart deleted file mode 100644 index ee9e673c5..000000000 --- a/lib/models/isar/models/silent_payments/silent_payment_output.g.dart +++ /dev/null @@ -1,2752 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'silent_payment_output.dart'; - -// ************************************************************************** -// IsarCollectionGenerator -// ************************************************************************** - -// coverage:ignore-file -// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types - -extension GetSilentPaymentOutputCollection on Isar { - IsarCollection get silentPaymentOutputs => - this.collection(); -} - -const SilentPaymentOutputSchema = CollectionSchema( - name: r'SilentPaymentOutput', - id: 7199689495392272388, - properties: { - r'ageInDays': PropertySchema( - id: 0, - name: r'ageInDays', - type: IsarType.double, - ), - r'amount': PropertySchema( - id: 1, - name: r'amount', - type: IsarType.long, - ), - r'blockHeight': PropertySchema( - id: 2, - name: r'blockHeight', - type: IsarType.long, - ), - r'blockTime': PropertySchema( - id: 3, - name: r'blockTime', - type: IsarType.long, - ), - r'confirmations': PropertySchema( - id: 4, - name: r'confirmations', - type: IsarType.long, - ), - r'isConfirmedSpent': PropertySchema( - id: 5, - name: r'isConfirmedSpent', - type: IsarType.bool, - ), - r'isSpent': PropertySchema( - id: 6, - name: r'isSpent', - type: IsarType.bool, - ), - r'label': PropertySchema( - id: 7, - name: r'label', - type: IsarType.string, - ), - r'outpoint': PropertySchema( - id: 8, - name: r'outpoint', - type: IsarType.string, - ), - r'outputScript': PropertySchema( - id: 9, - name: r'outputScript', - type: IsarType.string, - ), - r'privKeyTweak': PropertySchema( - id: 10, - name: r'privKeyTweak', - type: IsarType.string, - ), - r'spentBlockHeight': PropertySchema( - id: 11, - name: r'spentBlockHeight', - type: IsarType.long, - ), - r'spentBlockTime': PropertySchema( - id: 12, - name: r'spentBlockTime', - type: IsarType.long, - ), - r'spentTxid': PropertySchema( - id: 13, - name: r'spentTxid', - type: IsarType.string, - ), - r'txid': PropertySchema( - id: 14, - name: r'txid', - type: IsarType.string, - ), - r'vout': PropertySchema( - id: 15, - name: r'vout', - type: IsarType.long, - ), - r'walletId': PropertySchema( - id: 16, - name: r'walletId', - type: IsarType.string, - ) - }, - estimateSize: _silentPaymentOutputEstimateSize, - serialize: _silentPaymentOutputSerialize, - deserialize: _silentPaymentOutputDeserialize, - deserializeProp: _silentPaymentOutputDeserializeProp, - idName: r'id', - indexes: { - r'walletId_outputScript': IndexSchema( - id: -4581886294710132914, - name: r'walletId_outputScript', - unique: false, - replace: false, - properties: [ - IndexPropertySchema( - name: r'walletId', - type: IndexType.hash, - caseSensitive: true, - ), - IndexPropertySchema( - name: r'outputScript', - type: IndexType.hash, - caseSensitive: true, - ) - ], - ) - }, - links: {}, - embeddedSchemas: {}, - getId: _silentPaymentOutputGetId, - getLinks: _silentPaymentOutputGetLinks, - attach: _silentPaymentOutputAttach, - version: '3.1.8', -); - -int _silentPaymentOutputEstimateSize( - SilentPaymentOutput object, - List offsets, - Map> allOffsets, -) { - var bytesCount = offsets.last; - { - final value = object.label; - if (value != null) { - bytesCount += 3 + value.length * 3; - } - } - bytesCount += 3 + object.outpoint.length * 3; - bytesCount += 3 + object.outputScript.length * 3; - bytesCount += 3 + object.privKeyTweak.length * 3; - { - final value = object.spentTxid; - if (value != null) { - bytesCount += 3 + value.length * 3; - } - } - bytesCount += 3 + object.txid.length * 3; - bytesCount += 3 + object.walletId.length * 3; - return bytesCount; -} - -void _silentPaymentOutputSerialize( - SilentPaymentOutput object, - IsarWriter writer, - List offsets, - Map> allOffsets, -) { - writer.writeDouble(offsets[0], object.ageInDays); - writer.writeLong(offsets[1], object.amount); - writer.writeLong(offsets[2], object.blockHeight); - writer.writeLong(offsets[3], object.blockTime); - writer.writeLong(offsets[4], object.confirmations); - writer.writeBool(offsets[5], object.isConfirmedSpent); - writer.writeBool(offsets[6], object.isSpent); - writer.writeString(offsets[7], object.label); - writer.writeString(offsets[8], object.outpoint); - writer.writeString(offsets[9], object.outputScript); - writer.writeString(offsets[10], object.privKeyTweak); - writer.writeLong(offsets[11], object.spentBlockHeight); - writer.writeLong(offsets[12], object.spentBlockTime); - writer.writeString(offsets[13], object.spentTxid); - writer.writeString(offsets[14], object.txid); - writer.writeLong(offsets[15], object.vout); - writer.writeString(offsets[16], object.walletId); -} - -SilentPaymentOutput _silentPaymentOutputDeserialize( - Id id, - IsarReader reader, - List offsets, - Map> allOffsets, -) { - final object = SilentPaymentOutput( - amount: reader.readLong(offsets[1]), - blockHeight: reader.readLong(offsets[2]), - blockTime: reader.readLong(offsets[3]), - isSpent: reader.readBoolOrNull(offsets[6]) ?? false, - label: reader.readStringOrNull(offsets[7]), - outputScript: reader.readString(offsets[9]), - privKeyTweak: reader.readString(offsets[10]), - spentBlockHeight: reader.readLongOrNull(offsets[11]), - spentBlockTime: reader.readLongOrNull(offsets[12]), - spentTxid: reader.readStringOrNull(offsets[13]), - txid: reader.readString(offsets[14]), - vout: reader.readLong(offsets[15]), - walletId: reader.readString(offsets[16]), - ); - object.id = id; - return object; -} - -P _silentPaymentOutputDeserializeProp

( - IsarReader reader, - int propertyId, - int offset, - Map> allOffsets, -) { - switch (propertyId) { - case 0: - return (reader.readDouble(offset)) as P; - case 1: - return (reader.readLong(offset)) as P; - case 2: - return (reader.readLong(offset)) as P; - case 3: - return (reader.readLong(offset)) as P; - case 4: - return (reader.readLong(offset)) as P; - case 5: - return (reader.readBool(offset)) as P; - case 6: - return (reader.readBoolOrNull(offset) ?? false) as P; - case 7: - return (reader.readStringOrNull(offset)) as P; - case 8: - return (reader.readString(offset)) as P; - case 9: - return (reader.readString(offset)) as P; - case 10: - return (reader.readString(offset)) as P; - case 11: - return (reader.readLongOrNull(offset)) as P; - case 12: - return (reader.readLongOrNull(offset)) as P; - case 13: - return (reader.readStringOrNull(offset)) as P; - case 14: - return (reader.readString(offset)) as P; - case 15: - return (reader.readLong(offset)) as P; - case 16: - return (reader.readString(offset)) as P; - default: - throw IsarError('Unknown property with id $propertyId'); - } -} - -Id _silentPaymentOutputGetId(SilentPaymentOutput object) { - return object.id; -} - -List> _silentPaymentOutputGetLinks( - SilentPaymentOutput object) { - return []; -} - -void _silentPaymentOutputAttach( - IsarCollection col, Id id, SilentPaymentOutput object) { - object.id = id; -} - -extension SilentPaymentOutputQueryWhereSort - on QueryBuilder { - QueryBuilder anyId() { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(const IdWhereClause.any()); - }); - } -} - -extension SilentPaymentOutputQueryWhere - on QueryBuilder { - QueryBuilder - idEqualTo(Id id) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IdWhereClause.between( - lower: id, - upper: id, - )); - }); - } - - QueryBuilder - idNotEqualTo(Id id) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: false), - ) - .addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: false), - ); - } else { - return query - .addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: false), - ) - .addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: false), - ); - } - }); - } - - QueryBuilder - idGreaterThan(Id id, {bool include = false}) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - IdWhereClause.greaterThan(lower: id, includeLower: include), - ); - }); - } - - QueryBuilder - idLessThan(Id id, {bool include = false}) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - IdWhereClause.lessThan(upper: id, includeUpper: include), - ); - }); - } - - QueryBuilder - idBetween( - Id lowerId, - Id upperId, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IdWhereClause.between( - lower: lowerId, - includeLower: includeLower, - upper: upperId, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - walletIdEqualToAnyOutputScript(String walletId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'walletId_outputScript', - value: [walletId], - )); - }); - } - - QueryBuilder - walletIdNotEqualToAnyOutputScript(String walletId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [], - upper: [walletId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [walletId], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [walletId], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [], - upper: [walletId], - includeUpper: false, - )); - } - }); - } - - QueryBuilder - walletIdOutputScriptEqualTo(String walletId, String outputScript) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'walletId_outputScript', - value: [walletId, outputScript], - )); - }); - } - - QueryBuilder - walletIdEqualToOutputScriptNotEqualTo( - String walletId, String outputScript) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [walletId], - upper: [walletId, outputScript], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [walletId, outputScript], - includeLower: false, - upper: [walletId], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [walletId, outputScript], - includeLower: false, - upper: [walletId], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId_outputScript', - lower: [walletId], - upper: [walletId, outputScript], - includeUpper: false, - )); - } - }); - } -} - -extension SilentPaymentOutputQueryFilter on QueryBuilder { - QueryBuilder - ageInDaysEqualTo( - double value, { - double epsilon = Query.epsilon, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'ageInDays', - value: value, - epsilon: epsilon, - )); - }); - } - - QueryBuilder - ageInDaysGreaterThan( - double value, { - bool include = false, - double epsilon = Query.epsilon, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'ageInDays', - value: value, - epsilon: epsilon, - )); - }); - } - - QueryBuilder - ageInDaysLessThan( - double value, { - bool include = false, - double epsilon = Query.epsilon, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'ageInDays', - value: value, - epsilon: epsilon, - )); - }); - } - - QueryBuilder - ageInDaysBetween( - double lower, - double upper, { - bool includeLower = true, - bool includeUpper = true, - double epsilon = Query.epsilon, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'ageInDays', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - epsilon: epsilon, - )); - }); - } - - QueryBuilder - amountEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'amount', - value: value, - )); - }); - } - - QueryBuilder - amountGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'amount', - value: value, - )); - }); - } - - QueryBuilder - amountLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'amount', - value: value, - )); - }); - } - - QueryBuilder - amountBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'amount', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - blockHeightEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'blockHeight', - value: value, - )); - }); - } - - QueryBuilder - blockHeightGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'blockHeight', - value: value, - )); - }); - } - - QueryBuilder - blockHeightLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'blockHeight', - value: value, - )); - }); - } - - QueryBuilder - blockHeightBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'blockHeight', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - blockTimeEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'blockTime', - value: value, - )); - }); - } - - QueryBuilder - blockTimeGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'blockTime', - value: value, - )); - }); - } - - QueryBuilder - blockTimeLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'blockTime', - value: value, - )); - }); - } - - QueryBuilder - blockTimeBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'blockTime', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - confirmationsEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'confirmations', - value: value, - )); - }); - } - - QueryBuilder - confirmationsGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'confirmations', - value: value, - )); - }); - } - - QueryBuilder - confirmationsLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'confirmations', - value: value, - )); - }); - } - - QueryBuilder - confirmationsBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'confirmations', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - idEqualTo(Id value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'id', - value: value, - )); - }); - } - - QueryBuilder - idGreaterThan( - Id value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'id', - value: value, - )); - }); - } - - QueryBuilder - idLessThan( - Id value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'id', - value: value, - )); - }); - } - - QueryBuilder - idBetween( - Id lower, - Id upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'id', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - isConfirmedSpentEqualTo(bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isConfirmedSpent', - value: value, - )); - }); - } - - QueryBuilder - isSpentEqualTo(bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isSpent', - value: value, - )); - }); - } - - QueryBuilder - labelIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'label', - )); - }); - } - - QueryBuilder - labelIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'label', - )); - }); - } - - QueryBuilder - labelEqualTo( - String? value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'label', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelGreaterThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'label', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelLessThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'label', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelBetween( - String? lower, - String? upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'label', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'label', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'label', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'label', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'label', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - labelIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'label', - value: '', - )); - }); - } - - QueryBuilder - labelIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'label', - value: '', - )); - }); - } - - QueryBuilder - outpointEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'outpoint', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'outpoint', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'outpoint', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'outpoint', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'outpoint', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'outpoint', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'outpoint', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'outpoint', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outpointIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'outpoint', - value: '', - )); - }); - } - - QueryBuilder - outpointIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'outpoint', - value: '', - )); - }); - } - - QueryBuilder - outputScriptEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'outputScript', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'outputScript', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'outputScript', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'outputScript', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'outputScript', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'outputScript', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'outputScript', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'outputScript', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - outputScriptIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'outputScript', - value: '', - )); - }); - } - - QueryBuilder - outputScriptIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'outputScript', - value: '', - )); - }); - } - - QueryBuilder - privKeyTweakEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'privKeyTweak', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'privKeyTweak', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'privKeyTweak', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'privKeyTweak', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'privKeyTweak', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'privKeyTweak', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'privKeyTweak', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'privKeyTweak', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - privKeyTweakIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'privKeyTweak', - value: '', - )); - }); - } - - QueryBuilder - privKeyTweakIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'privKeyTweak', - value: '', - )); - }); - } - - QueryBuilder - spentBlockHeightIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'spentBlockHeight', - )); - }); - } - - QueryBuilder - spentBlockHeightIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'spentBlockHeight', - )); - }); - } - - QueryBuilder - spentBlockHeightEqualTo(int? value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'spentBlockHeight', - value: value, - )); - }); - } - - QueryBuilder - spentBlockHeightGreaterThan( - int? value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'spentBlockHeight', - value: value, - )); - }); - } - - QueryBuilder - spentBlockHeightLessThan( - int? value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'spentBlockHeight', - value: value, - )); - }); - } - - QueryBuilder - spentBlockHeightBetween( - int? lower, - int? upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'spentBlockHeight', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - spentBlockTimeIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'spentBlockTime', - )); - }); - } - - QueryBuilder - spentBlockTimeIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'spentBlockTime', - )); - }); - } - - QueryBuilder - spentBlockTimeEqualTo(int? value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'spentBlockTime', - value: value, - )); - }); - } - - QueryBuilder - spentBlockTimeGreaterThan( - int? value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'spentBlockTime', - value: value, - )); - }); - } - - QueryBuilder - spentBlockTimeLessThan( - int? value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'spentBlockTime', - value: value, - )); - }); - } - - QueryBuilder - spentBlockTimeBetween( - int? lower, - int? upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'spentBlockTime', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - spentTxidIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'spentTxid', - )); - }); - } - - QueryBuilder - spentTxidIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'spentTxid', - )); - }); - } - - QueryBuilder - spentTxidEqualTo( - String? value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'spentTxid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidGreaterThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'spentTxid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidLessThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'spentTxid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidBetween( - String? lower, - String? upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'spentTxid', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'spentTxid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'spentTxid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'spentTxid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'spentTxid', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - spentTxidIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'spentTxid', - value: '', - )); - }); - } - - QueryBuilder - spentTxidIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'spentTxid', - value: '', - )); - }); - } - - QueryBuilder - txidEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'txid', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'txid', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'txid', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - txidIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'txid', - value: '', - )); - }); - } - - QueryBuilder - txidIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'txid', - value: '', - )); - }); - } - - QueryBuilder - voutEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'vout', - value: value, - )); - }); - } - - QueryBuilder - voutGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'vout', - value: value, - )); - }); - } - - QueryBuilder - voutLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'vout', - value: value, - )); - }); - } - - QueryBuilder - voutBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'vout', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - walletIdEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'walletId', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'walletId', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: '', - )); - }); - } - - QueryBuilder - walletIdIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'walletId', - value: '', - )); - }); - } -} - -extension SilentPaymentOutputQueryObject on QueryBuilder {} - -extension SilentPaymentOutputQueryLinks on QueryBuilder {} - -extension SilentPaymentOutputQuerySortBy - on QueryBuilder { - QueryBuilder - sortByAgeInDays() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'ageInDays', Sort.asc); - }); - } - - QueryBuilder - sortByAgeInDaysDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'ageInDays', Sort.desc); - }); - } - - QueryBuilder - sortByAmount() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'amount', Sort.asc); - }); - } - - QueryBuilder - sortByAmountDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'amount', Sort.desc); - }); - } - - QueryBuilder - sortByBlockHeight() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockHeight', Sort.asc); - }); - } - - QueryBuilder - sortByBlockHeightDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockHeight', Sort.desc); - }); - } - - QueryBuilder - sortByBlockTime() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockTime', Sort.asc); - }); - } - - QueryBuilder - sortByBlockTimeDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockTime', Sort.desc); - }); - } - - QueryBuilder - sortByConfirmations() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'confirmations', Sort.asc); - }); - } - - QueryBuilder - sortByConfirmationsDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'confirmations', Sort.desc); - }); - } - - QueryBuilder - sortByIsConfirmedSpent() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isConfirmedSpent', Sort.asc); - }); - } - - QueryBuilder - sortByIsConfirmedSpentDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isConfirmedSpent', Sort.desc); - }); - } - - QueryBuilder - sortByIsSpent() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isSpent', Sort.asc); - }); - } - - QueryBuilder - sortByIsSpentDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isSpent', Sort.desc); - }); - } - - QueryBuilder - sortByLabel() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.asc); - }); - } - - QueryBuilder - sortByLabelDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.desc); - }); - } - - QueryBuilder - sortByOutpoint() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outpoint', Sort.asc); - }); - } - - QueryBuilder - sortByOutpointDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outpoint', Sort.desc); - }); - } - - QueryBuilder - sortByOutputScript() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputScript', Sort.asc); - }); - } - - QueryBuilder - sortByOutputScriptDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputScript', Sort.desc); - }); - } - - QueryBuilder - sortByPrivKeyTweak() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.asc); - }); - } - - QueryBuilder - sortByPrivKeyTweakDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.desc); - }); - } - - QueryBuilder - sortBySpentBlockHeight() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockHeight', Sort.asc); - }); - } - - QueryBuilder - sortBySpentBlockHeightDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockHeight', Sort.desc); - }); - } - - QueryBuilder - sortBySpentBlockTime() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockTime', Sort.asc); - }); - } - - QueryBuilder - sortBySpentBlockTimeDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockTime', Sort.desc); - }); - } - - QueryBuilder - sortBySpentTxid() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentTxid', Sort.asc); - }); - } - - QueryBuilder - sortBySpentTxidDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentTxid', Sort.desc); - }); - } - - QueryBuilder - sortByTxid() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.asc); - }); - } - - QueryBuilder - sortByTxidDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.desc); - }); - } - - QueryBuilder - sortByVout() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'vout', Sort.asc); - }); - } - - QueryBuilder - sortByVoutDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'vout', Sort.desc); - }); - } - - QueryBuilder - sortByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder - sortByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension SilentPaymentOutputQuerySortThenBy - on QueryBuilder { - QueryBuilder - thenByAgeInDays() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'ageInDays', Sort.asc); - }); - } - - QueryBuilder - thenByAgeInDaysDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'ageInDays', Sort.desc); - }); - } - - QueryBuilder - thenByAmount() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'amount', Sort.asc); - }); - } - - QueryBuilder - thenByAmountDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'amount', Sort.desc); - }); - } - - QueryBuilder - thenByBlockHeight() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockHeight', Sort.asc); - }); - } - - QueryBuilder - thenByBlockHeightDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockHeight', Sort.desc); - }); - } - - QueryBuilder - thenByBlockTime() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockTime', Sort.asc); - }); - } - - QueryBuilder - thenByBlockTimeDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'blockTime', Sort.desc); - }); - } - - QueryBuilder - thenByConfirmations() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'confirmations', Sort.asc); - }); - } - - QueryBuilder - thenByConfirmationsDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'confirmations', Sort.desc); - }); - } - - QueryBuilder - thenById() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.asc); - }); - } - - QueryBuilder - thenByIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.desc); - }); - } - - QueryBuilder - thenByIsConfirmedSpent() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isConfirmedSpent', Sort.asc); - }); - } - - QueryBuilder - thenByIsConfirmedSpentDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isConfirmedSpent', Sort.desc); - }); - } - - QueryBuilder - thenByIsSpent() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isSpent', Sort.asc); - }); - } - - QueryBuilder - thenByIsSpentDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isSpent', Sort.desc); - }); - } - - QueryBuilder - thenByLabel() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.asc); - }); - } - - QueryBuilder - thenByLabelDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.desc); - }); - } - - QueryBuilder - thenByOutpoint() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outpoint', Sort.asc); - }); - } - - QueryBuilder - thenByOutpointDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outpoint', Sort.desc); - }); - } - - QueryBuilder - thenByOutputScript() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputScript', Sort.asc); - }); - } - - QueryBuilder - thenByOutputScriptDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputScript', Sort.desc); - }); - } - - QueryBuilder - thenByPrivKeyTweak() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.asc); - }); - } - - QueryBuilder - thenByPrivKeyTweakDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.desc); - }); - } - - QueryBuilder - thenBySpentBlockHeight() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockHeight', Sort.asc); - }); - } - - QueryBuilder - thenBySpentBlockHeightDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockHeight', Sort.desc); - }); - } - - QueryBuilder - thenBySpentBlockTime() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockTime', Sort.asc); - }); - } - - QueryBuilder - thenBySpentBlockTimeDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentBlockTime', Sort.desc); - }); - } - - QueryBuilder - thenBySpentTxid() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentTxid', Sort.asc); - }); - } - - QueryBuilder - thenBySpentTxidDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'spentTxid', Sort.desc); - }); - } - - QueryBuilder - thenByTxid() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.asc); - }); - } - - QueryBuilder - thenByTxidDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'txid', Sort.desc); - }); - } - - QueryBuilder - thenByVout() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'vout', Sort.asc); - }); - } - - QueryBuilder - thenByVoutDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'vout', Sort.desc); - }); - } - - QueryBuilder - thenByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder - thenByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension SilentPaymentOutputQueryWhereDistinct - on QueryBuilder { - QueryBuilder - distinctByAgeInDays() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'ageInDays'); - }); - } - - QueryBuilder - distinctByAmount() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'amount'); - }); - } - - QueryBuilder - distinctByBlockHeight() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'blockHeight'); - }); - } - - QueryBuilder - distinctByBlockTime() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'blockTime'); - }); - } - - QueryBuilder - distinctByConfirmations() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'confirmations'); - }); - } - - QueryBuilder - distinctByIsConfirmedSpent() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isConfirmedSpent'); - }); - } - - QueryBuilder - distinctByIsSpent() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isSpent'); - }); - } - - QueryBuilder - distinctByLabel({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'label', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByOutpoint({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'outpoint', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByOutputScript({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'outputScript', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByPrivKeyTweak({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'privKeyTweak', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctBySpentBlockHeight() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'spentBlockHeight'); - }); - } - - QueryBuilder - distinctBySpentBlockTime() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'spentBlockTime'); - }); - } - - QueryBuilder - distinctBySpentTxid({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'spentTxid', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByTxid({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'txid', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByVout() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'vout'); - }); - } - - QueryBuilder - distinctByWalletId({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); - }); - } -} - -extension SilentPaymentOutputQueryProperty - on QueryBuilder { - QueryBuilder idProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'id'); - }); - } - - QueryBuilder - ageInDaysProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'ageInDays'); - }); - } - - QueryBuilder amountProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'amount'); - }); - } - - QueryBuilder - blockHeightProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'blockHeight'); - }); - } - - QueryBuilder blockTimeProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'blockTime'); - }); - } - - QueryBuilder - confirmationsProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'confirmations'); - }); - } - - QueryBuilder - isConfirmedSpentProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isConfirmedSpent'); - }); - } - - QueryBuilder isSpentProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isSpent'); - }); - } - - QueryBuilder labelProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'label'); - }); - } - - QueryBuilder - outpointProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'outpoint'); - }); - } - - QueryBuilder - outputScriptProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'outputScript'); - }); - } - - QueryBuilder - privKeyTweakProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'privKeyTweak'); - }); - } - - QueryBuilder - spentBlockHeightProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'spentBlockHeight'); - }); - } - - QueryBuilder - spentBlockTimeProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'spentBlockTime'); - }); - } - - QueryBuilder - spentTxidProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'spentTxid'); - }); - } - - QueryBuilder txidProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'txid'); - }); - } - - QueryBuilder voutProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'vout'); - }); - } - - QueryBuilder - walletIdProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'walletId'); - }); - } -} From 815714e03069a92941902bd8b00effe904aa7799 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Wed, 30 Apr 2025 00:42:20 -0400 Subject: [PATCH 10/14] greatly simplify metadata --- .../silent_payment_metadata.dart | 67 +- .../silent_payment_metadata.g.dart | 990 ++---------------- 2 files changed, 84 insertions(+), 973 deletions(-) diff --git a/lib/models/isar/models/silent_payments/silent_payment_metadata.dart b/lib/models/isar/models/silent_payments/silent_payment_metadata.dart index b14cc7dd6..19c140624 100644 --- a/lib/models/isar/models/silent_payments/silent_payment_metadata.dart +++ b/lib/models/isar/models/silent_payments/silent_payment_metadata.dart @@ -5,68 +5,25 @@ part 'silent_payment_metadata.g.dart'; @Collection(accessor: "silentPaymentMetadata", inheritance: false) class SilentPaymentMetadata implements IsarId { + /// Primary key for this metadata entry. + /// Should be generated as a sha256 hash of '$txid:$vout:$walletId' @override - Id id = Isar.autoIncrement; + Id id; - // Link to the UTXO this metadata is associated with - @Index(unique: true) - final int utxoId; + /// Private key tweak needed to spend this output + final String tweak; - // The wallet ID for efficient querying - @Index() - final String walletId; - - // Private key tweak needed to spend this output - final String privKeyTweak; - - // Optional label for the silent payment + /// This is not a user-defined label but a cryptographic tag + /// that affects key derivation final String? label; - // Shared secret used to derive this output (optional - for reference only) - final String? sharedSecret; - - // Output index in the set of outputs derived from the same shared secret - final int outputIndex; - - SilentPaymentMetadata({ - required this.utxoId, - required this.walletId, - required this.privKeyTweak, - required this.outputIndex, - this.label, - this.sharedSecret, - }); + SilentPaymentMetadata({required this.id, required this.tweak, this.label}); - SilentPaymentMetadata copyWith({ - int? utxoId, - String? walletId, - String? privKeyTweak, - int? outputIndex, - String? label, - String? sharedSecret, - }) { + SilentPaymentMetadata copyWith({int? id, String? tweak, String? label}) { return SilentPaymentMetadata( - utxoId: utxoId ?? this.utxoId, - walletId: walletId ?? this.walletId, - privKeyTweak: privKeyTweak ?? this.privKeyTweak, - outputIndex: outputIndex ?? this.outputIndex, + id: id ?? this.id, + tweak: tweak ?? this.tweak, label: label ?? this.label, - sharedSecret: sharedSecret ?? this.sharedSecret, - )..id = id; - } - - Future updateLabel({ - required Isar isar, - required String? newLabel, - }) async { - final thisMetadata = await isar.silentPaymentMetadata.get(id) ?? this; - - if (thisMetadata.label != newLabel) { - await isar.writeTxn(() async { - await isar.silentPaymentMetadata.put( - thisMetadata.copyWith(label: newLabel), - ); - }); - } + ); } } diff --git a/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart b/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart index bb7a967ea..e4e9dbf77 100644 --- a/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart +++ b/lib/models/isar/models/silent_payments/silent_payment_metadata.g.dart @@ -23,29 +23,9 @@ const SilentPaymentMetadataSchema = CollectionSchema( name: r'label', type: IsarType.string, ), - r'outputIndex': PropertySchema( + r'tweak': PropertySchema( id: 1, - name: r'outputIndex', - type: IsarType.long, - ), - r'privKeyTweak': PropertySchema( - id: 2, - name: r'privKeyTweak', - type: IsarType.string, - ), - r'sharedSecret': PropertySchema( - id: 3, - name: r'sharedSecret', - type: IsarType.string, - ), - r'utxoId': PropertySchema( - id: 4, - name: r'utxoId', - type: IsarType.long, - ), - r'walletId': PropertySchema( - id: 5, - name: r'walletId', + name: r'tweak', type: IsarType.string, ) }, @@ -54,34 +34,7 @@ const SilentPaymentMetadataSchema = CollectionSchema( deserialize: _silentPaymentMetadataDeserialize, deserializeProp: _silentPaymentMetadataDeserializeProp, idName: r'id', - indexes: { - r'utxoId': IndexSchema( - id: 5379991336603932725, - name: r'utxoId', - unique: true, - replace: false, - properties: [ - IndexPropertySchema( - name: r'utxoId', - type: IndexType.value, - caseSensitive: false, - ) - ], - ), - r'walletId': IndexSchema( - id: -1783113319798776304, - name: r'walletId', - unique: false, - replace: false, - properties: [ - IndexPropertySchema( - name: r'walletId', - type: IndexType.hash, - caseSensitive: true, - ) - ], - ) - }, + indexes: {}, links: {}, embeddedSchemas: {}, getId: _silentPaymentMetadataGetId, @@ -102,14 +55,7 @@ int _silentPaymentMetadataEstimateSize( bytesCount += 3 + value.length * 3; } } - bytesCount += 3 + object.privKeyTweak.length * 3; - { - final value = object.sharedSecret; - if (value != null) { - bytesCount += 3 + value.length * 3; - } - } - bytesCount += 3 + object.walletId.length * 3; + bytesCount += 3 + object.tweak.length * 3; return bytesCount; } @@ -120,11 +66,7 @@ void _silentPaymentMetadataSerialize( Map> allOffsets, ) { writer.writeString(offsets[0], object.label); - writer.writeLong(offsets[1], object.outputIndex); - writer.writeString(offsets[2], object.privKeyTweak); - writer.writeString(offsets[3], object.sharedSecret); - writer.writeLong(offsets[4], object.utxoId); - writer.writeString(offsets[5], object.walletId); + writer.writeString(offsets[1], object.tweak); } SilentPaymentMetadata _silentPaymentMetadataDeserialize( @@ -134,14 +76,10 @@ SilentPaymentMetadata _silentPaymentMetadataDeserialize( Map> allOffsets, ) { final object = SilentPaymentMetadata( + id: id, label: reader.readStringOrNull(offsets[0]), - outputIndex: reader.readLong(offsets[1]), - privKeyTweak: reader.readString(offsets[2]), - sharedSecret: reader.readStringOrNull(offsets[3]), - utxoId: reader.readLong(offsets[4]), - walletId: reader.readString(offsets[5]), + tweak: reader.readString(offsets[1]), ); - object.id = id; return object; } @@ -155,14 +93,6 @@ P _silentPaymentMetadataDeserializeProp

( case 0: return (reader.readStringOrNull(offset)) as P; case 1: - return (reader.readLong(offset)) as P; - case 2: - return (reader.readString(offset)) as P; - case 3: - return (reader.readStringOrNull(offset)) as P; - case 4: - return (reader.readLong(offset)) as P; - case 5: return (reader.readString(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); @@ -183,62 +113,6 @@ void _silentPaymentMetadataAttach( object.id = id; } -extension SilentPaymentMetadataByIndex - on IsarCollection { - Future getByUtxoId(int utxoId) { - return getByIndex(r'utxoId', [utxoId]); - } - - SilentPaymentMetadata? getByUtxoIdSync(int utxoId) { - return getByIndexSync(r'utxoId', [utxoId]); - } - - Future deleteByUtxoId(int utxoId) { - return deleteByIndex(r'utxoId', [utxoId]); - } - - bool deleteByUtxoIdSync(int utxoId) { - return deleteByIndexSync(r'utxoId', [utxoId]); - } - - Future> getAllByUtxoId(List utxoIdValues) { - final values = utxoIdValues.map((e) => [e]).toList(); - return getAllByIndex(r'utxoId', values); - } - - List getAllByUtxoIdSync(List utxoIdValues) { - final values = utxoIdValues.map((e) => [e]).toList(); - return getAllByIndexSync(r'utxoId', values); - } - - Future deleteAllByUtxoId(List utxoIdValues) { - final values = utxoIdValues.map((e) => [e]).toList(); - return deleteAllByIndex(r'utxoId', values); - } - - int deleteAllByUtxoIdSync(List utxoIdValues) { - final values = utxoIdValues.map((e) => [e]).toList(); - return deleteAllByIndexSync(r'utxoId', values); - } - - Future putByUtxoId(SilentPaymentMetadata object) { - return putByIndex(r'utxoId', object); - } - - Id putByUtxoIdSync(SilentPaymentMetadata object, {bool saveLinks = true}) { - return putByIndexSync(r'utxoId', object, saveLinks: saveLinks); - } - - Future> putAllByUtxoId(List objects) { - return putAllByIndex(r'utxoId', objects); - } - - List putAllByUtxoIdSync(List objects, - {bool saveLinks = true}) { - return putAllByIndexSync(r'utxoId', objects, saveLinks: saveLinks); - } -} - extension SilentPaymentMetadataQueryWhereSort on QueryBuilder { QueryBuilder @@ -247,15 +121,6 @@ extension SilentPaymentMetadataQueryWhereSort return query.addWhereClause(const IdWhereClause.any()); }); } - - QueryBuilder - anyUtxoId() { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause( - const IndexWhereClause.any(indexName: r'utxoId'), - ); - }); - } } extension SilentPaymentMetadataQueryWhere on QueryBuilder - utxoIdEqualTo(int utxoId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'utxoId', - value: [utxoId], - )); - }); - } - - QueryBuilder - utxoIdNotEqualTo(int utxoId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [], - upper: [utxoId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [utxoId], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [utxoId], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [], - upper: [utxoId], - includeUpper: false, - )); - } - }); - } - - QueryBuilder - utxoIdGreaterThan( - int utxoId, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [utxoId], - includeLower: include, - upper: [], - )); - }); - } - - QueryBuilder - utxoIdLessThan( - int utxoId, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [], - upper: [utxoId], - includeUpper: include, - )); - }); - } - - QueryBuilder - utxoIdBetween( - int lowerUtxoId, - int upperUtxoId, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'utxoId', - lower: [lowerUtxoId], - includeLower: includeLower, - upper: [upperUtxoId], - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder - walletIdEqualTo(String walletId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'walletId', - value: [walletId], - )); - }); - } - - QueryBuilder - walletIdNotEqualTo(String walletId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [], - upper: [walletId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [walletId], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [walletId], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'walletId', - lower: [], - upper: [walletId], - includeUpper: false, - )); - } - }); - } } extension SilentPaymentMetadataQueryFilter on QueryBuilder< @@ -682,69 +409,13 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder outputIndexEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'outputIndex', - value: value, - )); - }); - } - - QueryBuilder outputIndexGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'outputIndex', - value: value, - )); - }); - } - - QueryBuilder outputIndexLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'outputIndex', - value: value, - )); - }); - } - - QueryBuilder outputIndexBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'outputIndex', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder privKeyTweakEqualTo( + QAfterFilterCondition> tweakEqualTo( String value, { bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( - property: r'privKeyTweak', + property: r'tweak', value: value, caseSensitive: caseSensitive, )); @@ -752,7 +423,7 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder privKeyTweakGreaterThan( + QAfterFilterCondition> tweakGreaterThan( String value, { bool include = false, bool caseSensitive = true, @@ -760,7 +431,7 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.greaterThan( include: include, - property: r'privKeyTweak', + property: r'tweak', value: value, caseSensitive: caseSensitive, )); @@ -768,7 +439,7 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder privKeyTweakLessThan( + QAfterFilterCondition> tweakLessThan( String value, { bool include = false, bool caseSensitive = true, @@ -776,7 +447,7 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.lessThan( include: include, - property: r'privKeyTweak', + property: r'tweak', value: value, caseSensitive: caseSensitive, )); @@ -784,7 +455,7 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder privKeyTweakBetween( + QAfterFilterCondition> tweakBetween( String lower, String upper, { bool includeLower = true, @@ -793,7 +464,7 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.between( - property: r'privKeyTweak', + property: r'tweak', lower: lower, includeLower: includeLower, upper: upper, @@ -804,13 +475,13 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder privKeyTweakStartsWith( + QAfterFilterCondition> tweakStartsWith( String value, { bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.startsWith( - property: r'privKeyTweak', + property: r'tweak', value: value, caseSensitive: caseSensitive, )); @@ -818,13 +489,13 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder privKeyTweakEndsWith( + QAfterFilterCondition> tweakEndsWith( String value, { bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.endsWith( - property: r'privKeyTweak', + property: r'tweak', value: value, caseSensitive: caseSensitive, )); @@ -833,10 +504,10 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< QueryBuilder - privKeyTweakContains(String value, {bool caseSensitive = true}) { + tweakContains(String value, {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.contains( - property: r'privKeyTweak', + property: r'tweak', value: value, caseSensitive: caseSensitive, )); @@ -845,10 +516,10 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< QueryBuilder - privKeyTweakMatches(String pattern, {bool caseSensitive = true}) { + tweakMatches(String pattern, {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.matches( - property: r'privKeyTweak', + property: r'tweak', wildcard: pattern, caseSensitive: caseSensitive, )); @@ -856,566 +527,104 @@ extension SilentPaymentMetadataQueryFilter on QueryBuilder< } QueryBuilder privKeyTweakIsEmpty() { + QAfterFilterCondition> tweakIsEmpty() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( - property: r'privKeyTweak', + property: r'tweak', value: '', )); }); } QueryBuilder privKeyTweakIsNotEmpty() { + QAfterFilterCondition> tweakIsNotEmpty() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.greaterThan( - property: r'privKeyTweak', + property: r'tweak', value: '', )); }); } +} - QueryBuilder sharedSecretIsNull() { +extension SilentPaymentMetadataQueryObject on QueryBuilder< + SilentPaymentMetadata, SilentPaymentMetadata, QFilterCondition> {} + +extension SilentPaymentMetadataQueryLinks on QueryBuilder {} + +extension SilentPaymentMetadataQuerySortBy + on QueryBuilder { + QueryBuilder + sortByLabel() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNull( - property: r'sharedSecret', - )); + return query.addSortBy(r'label', Sort.asc); }); } - QueryBuilder sharedSecretIsNotNull() { + QueryBuilder + sortByLabelDesc() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'sharedSecret', - )); + return query.addSortBy(r'label', Sort.desc); }); } - QueryBuilder sharedSecretEqualTo( - String? value, { - bool caseSensitive = true, - }) { + QueryBuilder + sortByTweak() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'sharedSecret', - value: value, - caseSensitive: caseSensitive, - )); + return query.addSortBy(r'tweak', Sort.asc); }); } - QueryBuilder sharedSecretGreaterThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { + QueryBuilder + sortByTweakDesc() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'sharedSecret', - value: value, - caseSensitive: caseSensitive, - )); + return query.addSortBy(r'tweak', Sort.desc); }); } +} - QueryBuilder sharedSecretLessThan( - String? value, { - bool include = false, - bool caseSensitive = true, - }) { +extension SilentPaymentMetadataQuerySortThenBy + on QueryBuilder { + QueryBuilder + thenById() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'sharedSecret', - value: value, - caseSensitive: caseSensitive, - )); + return query.addSortBy(r'id', Sort.asc); }); } - QueryBuilder sharedSecretBetween( - String? lower, - String? upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { + QueryBuilder + thenByIdDesc() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'sharedSecret', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); + return query.addSortBy(r'id', Sort.desc); }); } - QueryBuilder sharedSecretStartsWith( - String value, { - bool caseSensitive = true, - }) { + QueryBuilder + thenByLabel() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'sharedSecret', - value: value, - caseSensitive: caseSensitive, - )); + return query.addSortBy(r'label', Sort.asc); }); } - QueryBuilder sharedSecretEndsWith( - String value, { - bool caseSensitive = true, - }) { + QueryBuilder + thenByLabelDesc() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'sharedSecret', - value: value, - caseSensitive: caseSensitive, - )); + return query.addSortBy(r'label', Sort.desc); }); } - QueryBuilder - sharedSecretContains(String value, {bool caseSensitive = true}) { + QueryBuilder + thenByTweak() { return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'sharedSecret', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - sharedSecretMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'sharedSecret', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder sharedSecretIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'sharedSecret', - value: '', - )); - }); - } - - QueryBuilder sharedSecretIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'sharedSecret', - value: '', - )); - }); - } - - QueryBuilder utxoIdEqualTo(int value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'utxoId', - value: value, - )); - }); - } - - QueryBuilder utxoIdGreaterThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'utxoId', - value: value, - )); - }); - } - - QueryBuilder utxoIdLessThan( - int value, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'utxoId', - value: value, - )); - }); - } - - QueryBuilder utxoIdBetween( - int lower, - int upper, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'utxoId', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - )); - }); - } - - QueryBuilder walletIdEqualTo( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder walletIdGreaterThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder walletIdLessThan( - String value, { - bool include = false, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.lessThan( - include: include, - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder walletIdBetween( - String lower, - String upper, { - bool includeLower = true, - bool includeUpper = true, - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.between( - property: r'walletId', - lower: lower, - includeLower: includeLower, - upper: upper, - includeUpper: includeUpper, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder walletIdStartsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.startsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder walletIdEndsWith( - String value, { - bool caseSensitive = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.endsWith( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdContains(String value, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.contains( - property: r'walletId', - value: value, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder - walletIdMatches(String pattern, {bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.matches( - property: r'walletId', - wildcard: pattern, - caseSensitive: caseSensitive, - )); - }); - } - - QueryBuilder walletIdIsEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'walletId', - value: '', - )); - }); - } - - QueryBuilder walletIdIsNotEmpty() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.greaterThan( - property: r'walletId', - value: '', - )); - }); - } -} - -extension SilentPaymentMetadataQueryObject on QueryBuilder< - SilentPaymentMetadata, SilentPaymentMetadata, QFilterCondition> {} - -extension SilentPaymentMetadataQueryLinks on QueryBuilder {} - -extension SilentPaymentMetadataQuerySortBy - on QueryBuilder { - QueryBuilder - sortByLabel() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.asc); - }); - } - - QueryBuilder - sortByLabelDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.desc); - }); - } - - QueryBuilder - sortByOutputIndex() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputIndex', Sort.asc); - }); - } - - QueryBuilder - sortByOutputIndexDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputIndex', Sort.desc); - }); - } - - QueryBuilder - sortByPrivKeyTweak() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.asc); - }); - } - - QueryBuilder - sortByPrivKeyTweakDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.desc); - }); - } - - QueryBuilder - sortBySharedSecret() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'sharedSecret', Sort.asc); - }); - } - - QueryBuilder - sortBySharedSecretDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'sharedSecret', Sort.desc); - }); - } - - QueryBuilder - sortByUtxoId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'utxoId', Sort.asc); - }); - } - - QueryBuilder - sortByUtxoIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'utxoId', Sort.desc); - }); - } - - QueryBuilder - sortByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); + return query.addSortBy(r'tweak', Sort.asc); }); } QueryBuilder - sortByWalletIdDesc() { + thenByTweakDesc() { return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); - }); - } -} - -extension SilentPaymentMetadataQuerySortThenBy - on QueryBuilder { - QueryBuilder - thenById() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.asc); - }); - } - - QueryBuilder - thenByIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'id', Sort.desc); - }); - } - - QueryBuilder - thenByLabel() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.asc); - }); - } - - QueryBuilder - thenByLabelDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'label', Sort.desc); - }); - } - - QueryBuilder - thenByOutputIndex() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputIndex', Sort.asc); - }); - } - - QueryBuilder - thenByOutputIndexDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'outputIndex', Sort.desc); - }); - } - - QueryBuilder - thenByPrivKeyTweak() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.asc); - }); - } - - QueryBuilder - thenByPrivKeyTweakDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'privKeyTweak', Sort.desc); - }); - } - - QueryBuilder - thenBySharedSecret() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'sharedSecret', Sort.asc); - }); - } - - QueryBuilder - thenBySharedSecretDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'sharedSecret', Sort.desc); - }); - } - - QueryBuilder - thenByUtxoId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'utxoId', Sort.asc); - }); - } - - QueryBuilder - thenByUtxoIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'utxoId', Sort.desc); - }); - } - - QueryBuilder - thenByWalletId() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.asc); - }); - } - - QueryBuilder - thenByWalletIdDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'walletId', Sort.desc); + return query.addSortBy(r'tweak', Sort.desc); }); } } @@ -1430,37 +639,9 @@ extension SilentPaymentMetadataQueryWhereDistinct } QueryBuilder - distinctByOutputIndex() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'outputIndex'); - }); - } - - QueryBuilder - distinctByPrivKeyTweak({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'privKeyTweak', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctBySharedSecret({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'sharedSecret', caseSensitive: caseSensitive); - }); - } - - QueryBuilder - distinctByUtxoId() { + distinctByTweak({bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'utxoId'); - }); - } - - QueryBuilder - distinctByWalletId({bool caseSensitive = true}) { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive); + return query.addDistinctBy(r'tweak', caseSensitive: caseSensitive); }); } } @@ -1480,37 +661,10 @@ extension SilentPaymentMetadataQueryProperty on QueryBuilder< }); } - QueryBuilder - outputIndexProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'outputIndex'); - }); - } - - QueryBuilder - privKeyTweakProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'privKeyTweak'); - }); - } - - QueryBuilder - sharedSecretProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'sharedSecret'); - }); - } - - QueryBuilder utxoIdProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'utxoId'); - }); - } - QueryBuilder - walletIdProperty() { + tweakProperty() { return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'walletId'); + return query.addPropertyName(r'tweak'); }); } } From f70c9ebfb4db8bfa1eb69f965e06b877b9309a6c Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Wed, 30 Apr 2025 00:42:37 -0400 Subject: [PATCH 11/14] add new schemas to MainDB --- lib/db/isar/main_db.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/db/isar/main_db.dart b/lib/db/isar/main_db.dart index a16fb2b9a..6f52a58e3 100644 --- a/lib/db/isar/main_db.dart +++ b/lib/db/isar/main_db.dart @@ -19,6 +19,8 @@ import '../../models/isar/models/contact_entry.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/isar/ordinal.dart'; import '../../models/isar/stack_theme.dart'; +import '../../models/isar/models/silent_payments/silent_payment_config.dart'; +import '../../models/isar/models/silent_payments/silent_payment_metadata.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/extensions/extensions.dart'; import '../../utilities/stack_file_system.dart'; @@ -70,6 +72,8 @@ class MainDB { WalletInfoMetaSchema, TokenWalletInfoSchema, FrostWalletInfoSchema, + SilentPaymentConfigSchema, + SilentPaymentMetadataSchema, ], directory: (await StackFileSystem.applicationIsarDirectory()).path, // inspector: kDebugMode, From 7a65da21890e229f21700c5b946842980d74338c Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Wed, 30 Apr 2025 00:43:07 -0400 Subject: [PATCH 12/14] add a silent payments provider --- .../silent_payment_provider.dart | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 lib/providers/silent_payment/silent_payment_provider.dart diff --git a/lib/providers/silent_payment/silent_payment_provider.dart b/lib/providers/silent_payment/silent_payment_provider.dart new file mode 100644 index 000000000..64fd13dc2 --- /dev/null +++ b/lib/providers/silent_payment/silent_payment_provider.dart @@ -0,0 +1,90 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; + +import '../../models/isar/models/silent_payments/silent_payment_config.dart'; +import '../../models/isar/models/silent_payments/silent_payment_metadata.dart'; +import '../../providers/db/main_db_provider.dart'; +import '../../wallets/isar/providers/util/watcher.dart'; +import '../../wallets/isar/providers/wallet_info_provider.dart'; + +/// Base provider that watches the SilentPaymentConfig object in the database +final _silentPaymentConfigProvider = + ChangeNotifierProvider.family((ref, walletId) { + final isar = ref.watch(mainDBProvider).isar; + final collection = isar.silentPaymentConfig; + + // Try to find existing config + var config = collection.where().walletIdEqualTo(walletId).findFirstSync(); + + // If no config exists, create and save a new one + if (config == null) { + config = SilentPaymentConfig(walletId: walletId); + isar.writeTxnSync(() { + isar.silentPaymentConfig.putSync(config!); + }); + } + + // Create a watcher for this config + final watcher = Watcher(config, collection: collection); + + // Clean up when provider is disposed + ref.onDispose(() => watcher.dispose()); + + return watcher; + }); + +/// Provider for the entire SilentPaymentConfig object +final pSilentPaymentConfig = Provider.family(( + ref, + walletId, +) { + return ref.watch(_silentPaymentConfigProvider(walletId)).value + as SilentPaymentConfig; +}); + +/// Provider for just the enabled state +final pSilentPaymentEnabled = Provider.family((ref, walletId) { + return ref.watch( + _silentPaymentConfigProvider( + walletId, + ).select((value) => (value.value as SilentPaymentConfig).isEnabled), + ); +}); + +/// Provider for the last scanned height +final pSilentPaymentLastScannedHeight = Provider.family(( + ref, + walletId, +) { + return ref.watch( + _silentPaymentConfigProvider( + walletId, + ).select((value) => (value.value as SilentPaymentConfig).lastScannedHeight), + ); +}); + +/// Provider for the label map +final pSilentPaymentLabelMap = Provider.family?, String>(( + ref, + walletId, +) { + return ref.watch( + _silentPaymentConfigProvider( + walletId, + ).select((value) => (value.value as SilentPaymentConfig).labelMap), + ); +}); + +/// Provider to determine if scanning is needed (compares with wallet height) +final pSilentPaymentScanNeeded = Provider.family((ref, walletId) { + final config = ref.watch(pSilentPaymentConfig(walletId)); + + // Import the wallet chain height provider where needed + try { + final walletHeight = ref.watch(pWalletChainHeight(walletId)); + return config.isEnabled && walletHeight > config.lastScannedHeight; + } catch (_) { + // Handle case where pWalletChainHeight isn't imported + return false; + } +}); From 335c660eddac01840180ea8bab9d1c424544d5e4 Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Thu, 1 May 2025 13:44:45 -0400 Subject: [PATCH 13/14] wip: silent payment interface --- .../silent_payments/silent_payments_view.dart | 109 +++- .../silent_payment_interface.dart | 517 ++++++++++++++++++ 2 files changed, 621 insertions(+), 5 deletions(-) create mode 100644 lib/wallets/wallet/wallet_mixin_interfaces/silent_payment_interface.dart diff --git a/lib/pages/silent_payments/silent_payments_view.dart b/lib/pages/silent_payments/silent_payments_view.dart index df85cb9cc..7c73ec4ce 100644 --- a/lib/pages/silent_payments/silent_payments_view.dart +++ b/lib/pages/silent_payments/silent_payments_view.dart @@ -2,14 +2,18 @@ import 'dart:async'; +import 'package:coinlib_flutter/coinlib_flutter.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:isar/isar.dart'; import '../../../wallets/wallet/impl/bitcoin_wallet.dart'; import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/wallets_provider.dart'; +import '../../models/isar/models/isar_models.dart'; +import '../../providers/silent_payment/silent_payment_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../notifications/show_flush_bar.dart'; @@ -29,6 +33,7 @@ import '../../widgets/icon_widgets/copy_icon.dart'; import '../../widgets/rounded_white_container.dart'; import 'package:silent_payments/silent_payments.dart'; +import 'package:coinlib/src/tx/outpoint.dart'; class SilentPaymentsView extends ConsumerStatefulWidget { const SilentPaymentsView({super.key, required this.walletId}); @@ -89,6 +94,13 @@ class _SilentPaymentsViewState extends ConsumerState { _scanPrivateKey = owner.b_scan.data.toHex; _spendPrivateKey = owner.b_spend.data.toHex; + // Initialize UI state from config + final config = ref.read(pSilentPaymentConfig(widget.walletId)); + + setState(() { + _enabled = config.isEnabled; + }); + // Update debug info _debugInfo.clear(); _debugInfo.addAll({ @@ -106,6 +118,18 @@ class _SilentPaymentsViewState extends ConsumerState { super.dispose(); } + // Example: Toggle silent payments on/off + Future _toggleSilentPayments(bool enabled) async { + final isar = ref.read(mainDBProvider).isar; + final config = ref.read(pSilentPaymentConfig(widget.walletId)); + await config.updateEnabled(enabled: enabled, isar: isar); + + // Update the local state to reflect the change + setState(() { + _enabled = enabled; + }); + } + // Mock sending silent payment Future _sendSilentPayment() async { final recipientAddress = _recipientAddressController.text.trim(); @@ -159,6 +183,83 @@ class _SilentPaymentsViewState extends ConsumerState { // 3. Generate output addresses // 4. Broadcast the transaction + // Get Bitcoin wallet instance + final wallet = + ref.read(pWallets).getWallet(widget.walletId) as BitcoinWallet; + final mainDB = wallet.mainDB; + final root = await wallet.getRootHDNode(); + + // Amount in satoshis + final satoshiAmount = (double.parse(amount) * 100000000).toInt(); + + // Get available UTXOs + // final isar = mainDB.isar; + // final utxos = + // await isar.utxos + // .filter() + // .walletIdEqualTo(widget.walletId) + // .usedEqualTo(false) + // .findAll(); + final utxos = + await mainDB + .getUTXOs(widget.walletId) + .filter() + .usedEqualTo(false) + .findAll(); + + final signingData = await wallet.fetchBuildTxData(utxos); + + final selectedUtxos = []; + int runningTotal = 0; + final int estimatedFee = 1000; + + for (final utxo in utxos) { + selectedUtxos.add(utxo); + runningTotal += utxo.value; + + if (runningTotal >= satoshiAmount + estimatedFee) { + break; + } + } + + // Convert UTXOs to outpoints + final outpoints = + selectedUtxos.map((utxo) { + return OutPoint(utxo.txid.toUint8ListFromHex, utxo.vout); + }).toList(); + + final inputPrivateInfos = + selectedUtxos.map((utxo) async { + // TODO: figure out how to get private key for each outpoint + final address = await mainDB.getAddress( + wallet.walletId, + utxo.address!, + ); + final keys = root.derivePath(address.derivationPath!.value); + final ECPrivateKey privkey; + final bool isTaproot; + return ECPrivateInfo(privkey, isTaproot); + }).toList(); + + // Prepare destination addresses + final destinations = [ + SilentPaymentDestination.fromAddress(recipientAddress, 0), + ]; + + final inputPubKeys = + inputPrivateInfos.map((info) => info.privkey.pubkey).toList(); + + final builder = SilentPaymentBuilder( + outpoints: outpoints, + publicKeys: inputPubKeys, + ); + + final outputMap = builder.createOutputs(inputPrivateInfos, destinations); + final sendingOutputs = + outputMap.values + .expand((outputs) => outputs.map((o) => o.address.data.toHex)) + .toList(); + await Future.delayed(const Duration(seconds: 1)); // Mock transaction details for demonstration @@ -438,10 +539,8 @@ class _SilentPaymentsViewState extends ConsumerState { children: [ Switch( value: _enabled, - onChanged: (value) { - setState(() { - _enabled = value; - }); + onChanged: (value) async { + await _toggleSilentPayments(value); }, activeColor: colors.accentColorGreen, ), @@ -557,7 +656,7 @@ class _SilentPaymentsViewState extends ConsumerState { TextField( controller: _recipientAddressController, decoration: InputDecoration( - hintText: "sp1...", + hintText: "tsp1...", filled: true, fillColor: colors.textFieldDefaultBG, border: OutlineInputBorder( diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/silent_payment_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/silent_payment_interface.dart new file mode 100644 index 000000000..5c030921f --- /dev/null +++ b/lib/wallets/wallet/wallet_mixin_interfaces/silent_payment_interface.dart @@ -0,0 +1,517 @@ +import 'dart:async'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib; +import 'package:isar/isar.dart'; +import 'package:silent_payments/silent_payments.dart'; + +import '../../../electrumx_rpc/cached_electrumx_client.dart'; +import '../../../electrumx_rpc/client_manager.dart'; +import '../../../electrumx_rpc/electrumx_client.dart'; +import '../../../models/coinlib/exp2pkh_address.dart'; +import '../../../models/isar/models/blockchain_data/v2/input_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/output_v2.dart'; +import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; +import '../../../models/isar/models/isar_models.dart'; +import '../../../models/isar/models/silent_payments/silent_payment_config.dart'; +import '../../../models/isar/models/silent_payments/silent_payment_metadata.dart'; +import '../../../models/keys/view_only_wallet_data.dart'; +import '../../../models/paymint/fee_object_model.dart'; +import '../../../models/signing_data.dart'; +import '../../../utilities/amount/amount.dart'; +import '../../../utilities/enums/derive_path_type_enum.dart'; +import '../../../utilities/enums/fee_rate_type_enum.dart'; +import '../../../utilities/extensions/extensions.dart'; +import '../../../utilities/logger.dart'; +import '../../crypto_currency/crypto_currency.dart'; +import '../../crypto_currency/interfaces/electrumx_currency_interface.dart'; +import '../../isar/models/wallet_info.dart'; +import '../../models/tx_data.dart'; +import '../impl/bitcoin_wallet.dart'; +import '../intermediate/bip39_hd_wallet.dart'; +import 'electrumx_interface.dart'; +import 'view_only_option_interface.dart'; + +/// A mixin that provides Silent Payment capabilities to a wallet +/// +/// This interface focuses on the unique aspects of Silent Payments: +/// 1. Generating Silent Payment addresses +/// 2. Deriving recipient addresses for sending +/// 3. Scanning for received payments +/// +/// It leverages the existing wallet methods for transaction building +/// and blockchain interaction. +mixin SilentPaymentInterface + on ElectrumXInterface { + // Cache for the silent payment owner to avoid repetitive derivation + SilentPaymentOwner? _silentPaymentOwner; + + // Cached labeled addresses + final Map _labeledAddresses = {}; + + /// Whether Silent Payment scanning is enabled for this wallet + Future get isSilentPaymentScanningEnabled async { + final config = await _getSilentPaymentConfig(); + return config?.isEnabled ?? false; + } + + /// Set whether Silent Payment scanning is enabled + Future setSilentPaymentScanningEnabled(bool enabled) async { + final config = await _getSilentPaymentConfig(); + if (config != null) { + await config.updateEnabled(enabled: enabled, isar: mainDB.isar); + } else { + await mainDB.isar.writeTxn(() async { + await mainDB.isar.silentPaymentConfig.put( + SilentPaymentConfig(walletId: walletId, isEnabled: enabled), + ); + }); + } + } + + /// Get the wallet's Silent Payment address + /// + /// Returns the base Silent Payment address for this wallet + Future getSilentPaymentAddress() async { + final owner = await _getSilentPaymentOwner(); + return owner.toString(network: _getNetworkString()); + } + + /// Get the wallet's Silent Payment address with a specific label + /// + /// Labels allow a single Silent Payment address to be shared while + /// still allowing different addresses to be generated for different + /// uses or senders + Future getLabeledSilentPaymentAddress(int label) async { + final owner = await _getSilentPaymentOwner(); + + if (!_labeledAddresses.containsKey(label)) { + _labeledAddresses[label] = owner.toLabeledAddress(label); + } + + return _labeledAddresses[label]!.toString(network: _getNetworkString()); + } + + /// Derive the recipient address(es) for a Silent Payment transaction + /// + /// This can be used with your existing prepareSend method: + /// ``` + /// final selectedUtxos = await wallet.coinSelection(...); + /// final recipientAddress = await wallet.deriveSilentPaymentAddress("sp1...", selectedUtxos); + /// wallet.prepareSend(txData: TxData(recipients: [(address: recipientAddress, amount: amount)])); + /// ``` + Future deriveSilentPaymentAddress( + String silentPaymentAddress, + List selectedUtxos, { + int amount = 0, + }) async { + // Validate the recipient address + if (!SilentPaymentAddress.regex.hasMatch(silentPaymentAddress)) { + throw Exception("Invalid Silent Payment address format"); + } + + // Ensure we have UTXOs to work with + if (selectedUtxos.isEmpty) { + throw Exception("No UTXOs provided for the transaction"); + } + + // Create a destination from the address + final destination = SilentPaymentDestination.fromAddress( + silentPaymentAddress, + amount, + ); + + // Extract outpoints from selected UTXOs + final outpoints = + selectedUtxos + .map((utxo) => coinlib.OutPoint.fromHex(utxo.txid, utxo.vout)) + .toList(); + + // Get private keys for the inputs needed by the Silent Payment builder + final inputPrivKeyInfos = []; + final pubKeys = []; + + for (final utxo in selectedUtxos) { + final address = utxo.address!; + // TODO: convert to 'Address' type + final privkey = await getPrivateKey(address); + final isP2TR = address.startsWith('bc1p') || address.startsWith('tb1p'); + + inputPrivKeyInfos.add( + ECPrivateInfo(privkey, isP2TR, needsTweaking: isP2TR), + ); + + pubKeys.add(privkey.pubkey); + } + + // Create the Silent Payment Builder + final builder = SilentPaymentBuilder( + outpoints: outpoints, + publicKeys: pubKeys, + hrp: info.coin.network == CryptoCurrencyNetwork.main ? 'bc' : 'tb', + ); + + // Create the outputs - this is where the Silent Payment magic happens + final outputMap = builder.createOutputs(inputPrivKeyInfos, [destination]); + + // Extract the first output for the given destination + if (outputMap.isEmpty || + !outputMap.containsKey(silentPaymentAddress) || + outputMap[silentPaymentAddress]!.isEmpty) { + throw Exception("Failed to derive Silent Payment address"); + } + + return outputMap[silentPaymentAddress]!.first.address.toString(); + } + + /// Derive multiple recipient addresses for a batch of Silent Payment recipients + /// + /// This is useful for sending to multiple Silent Payment addresses in one transaction. + Future> deriveSilentPaymentAddresses( + Map silentPaymentAddressesWithAmounts, + List selectedUtxos, + ) async { + if (silentPaymentAddressesWithAmounts.isEmpty) { + return []; + } + + // Ensure we have UTXOs to work with + if (selectedUtxos.isEmpty) { + throw Exception("No UTXOs provided for the transaction"); + } + + // Create destinations from the addresses + final destinations = + silentPaymentAddressesWithAmounts.entries + .map( + (entry) => + SilentPaymentDestination.fromAddress(entry.key, entry.value), + ) + .toList(); + + // Extract outpoints from selected UTXOs + final outpoints = + selectedUtxos + .map((utxo) => coinlib.OutPoint.fromHex(utxo.txid, utxo.vout)) + .toList(); + + // Get private keys for the inputs needed by the Silent Payment builder + final inputPrivKeyInfos = []; + final pubKeys = []; + + for (final utxo in selectedUtxos) { + final address = utxo.address!; + final privkey = await getPrivateKey(address); + final isP2TR = address.startsWith('bc1p') || address.startsWith('tb1p'); + + inputPrivKeyInfos.add( + ECPrivateInfo(privkey, isP2TR, needsTweaking: isP2TR), + ); + + pubKeys.add(privkey.pubkey); + } + + // Create the Silent Payment Builder + final builder = SilentPaymentBuilder( + outpoints: outpoints, + publicKeys: pubKeys, + hrp: info.coin.network == CryptoCurrencyNetwork.main ? 'bc' : 'tb', + ); + + // Create the outputs - this is where the Silent Payment magic happens + final outputMap = builder.createOutputs(inputPrivKeyInfos, destinations); + + // Extract all derived addresses + final derivedAddresses = []; + for (final outputs in outputMap.values) { + for (final output in outputs) { + derivedAddresses.add(output.address.toString()); + } + } + + return derivedAddresses; + } + + /// Scan for Silent Payments in recent transactions + /// + /// This method checks recent blocks for transactions that contain + /// Silent Payments to this wallet. + /// + /// Returns a list of detected outputs with their details + Future>> scanForSilentPayments({ + int? fromHeight, + int? toHeight, + }) async { + final isEnabled = await isSilentPaymentScanningEnabled; + if (!isEnabled) { + return []; + } + + // Get the config to determine last scanned height + final config = await _getSilentPaymentConfig(); + if (config == null) { + return []; + } + + // Get heights to scan + final currentHeight = await chainHeight; + final scanFromHeight = + fromHeight ?? + (config.lastScannedHeight > 0 + ? config.lastScannedHeight + 1 + : currentHeight - 10); + final scanToHeight = toHeight ?? currentHeight; + + final foundOutputs = >[]; + + // Get the Silent Payment owner + final owner = await _getSilentPaymentOwner(); + + // Initialize precomputed labels from the config + final labelMap = config.labelMap; + + // Scan each block in the range + for (int height = scanFromHeight; height <= scanToHeight; height++) { + // Get transactions in the block + final blockHeader = await electrumXClient.getBlockHeadTip(); + + // TODO: Figure out how to get block tx data! + final txids = await getBlockTransactions(blockHeader['id']); + if (txids.isEmpty) continue; + + // Process each transaction + for (final txid in txids) { + final tx = await getTransaction(txid); + if (tx == null) continue; + + // Get inputs and outputs + final inputs = tx['vin'] as List; + final outputs = tx['vout'] as List; + + // Skip transactions with no inputs or outputs + if (inputs.isEmpty || outputs.isEmpty) continue; + + // Collect outpoints and input public keys + final outpoints = []; + final pubKeys = []; + + for (final input in inputs) { + final prevTxid = input['txid']; + final prevVout = input['vout']; + + if (prevTxid == null || prevVout == null) continue; + + outpoints.add(coinlib.OutPoint.fromHex(prevTxid, prevVout)); + + // Extract public key from input + final witnessData = input['txinwitness']; + if (witnessData is List && witnessData.isNotEmpty) { + try { + final pubkeyHex = witnessData.last; + pubKeys.add(coinlib.ECPublicKey.fromHex(pubkeyHex)); + } catch (_) { + // Skip if unable to extract public key + continue; + } + } + } + + // Skip if unable to extract public keys + if (pubKeys.isEmpty) continue; + + // Create SilentPaymentBuilder to scan outputs + final builder = SilentPaymentBuilder( + outpoints: outpoints, + publicKeys: pubKeys, + hrp: info.coin.network == CryptoCurrencyNetwork.main ? 'bc' : 'tb', + ); + + // Convert outputs to format expected by scanner + final outputsToCheck = []; + for (final output in outputs) { + final scriptPubKey = output['scriptPubKey']; + if (scriptPubKey == null) continue; + + final hexScript = scriptPubKey['hex']; + final value = output['value'] ?? 0; + + if (hexScript == null) continue; + + try { + outputsToCheck.add( + coinlib.Output.fromScriptBytes( + BigInt.from(value * 100000000), // Convert BTC to satoshis + hexToBytes(hexScript), + ), + ); + } catch (_) { + continue; + } + } + + // Scan for outputs belonging to this wallet + final scanResults = builder.scanOutputs( + owner, + outputsToCheck, + precomputedLabels: labelMap, + ); + + // Process found outputs + for (final result in scanResults.entries) { + final output = result.value.output; + final label = result.value.label; + + foundOutputs.add({ + 'txid': txid, + 'address': output.address.toString(), + 'amount': output.amount, + 'label': label, + 'derivedPrivateKey': bytesToHex( + owner.b_spend.tweak(hexToBytes(result.value.tweak))!.data, + ), + }); + + // Import the address to the wallet for tracking + await importAddress( + output.address.toString(), + AddressType.p2tr, + isChange: false, + ); + } + } + } + + // Update the last scanned height + if (scanToHeight > config.lastScannedHeight) { + await config.updateLastScannedHeight(height: scanToHeight, isar: mainDB); + } + + return foundOutputs; + } + + /// Add a label for the wallet's Silent Payment address + /// + /// Returns the labeled address + Future addSilentPaymentLabel(int label) async { + final owner = await _getSilentPaymentOwner(); + final labeledAddress = owner.toLabeledAddress(label); + + // Get or create the config + var config = await _getSilentPaymentConfig(); + if (config == null) { + await mainDB.writeTxn(() async { + await mainDB.silentPaymentConfig.put( + SilentPaymentConfig(walletId: walletId), + ); + }); + config = await _getSilentPaymentConfig(); + } + + if (config != null) { + // Generate label data + final generatedLabel = owner.generateLabel(label); + final G = ECPublicKey(ECCurve_secp256k1().G.getEncoded(true)); + + // Add to the config's label map + final labelMap = config.labelMap ?? {}; + labelMap[bytesToHex(tweakMulPublic(G, generatedLabel))] = bytesToHex( + generatedLabel, + ); + + await config.updateLabelMap(newLabelMap: labelMap, isar: mainDB); + } + + // Update cache + _labeledAddresses[label] = labeledAddress; + + return labeledAddress.toString(network: _getNetworkString()); + } + + /// Remove a label from the wallet's Silent Payment address + Future removeSilentPaymentLabel(int label) async { + final config = await _getSilentPaymentConfig(); + if (config == null || config.labelMap == null || config.labelMap!.isEmpty) { + return; + } + + // Generate label data + final owner = await _getSilentPaymentOwner(); + final generatedLabel = owner.generateLabel(label); + final G = ECPublicKey(ECCurve_secp256k1().G.getEncoded(true)); + final labelKey = bytesToHex(tweakMulPublic(G, generatedLabel)); + + // Check if the label exists + if (!config.labelMap!.containsKey(labelKey)) return; + + // Create new map without this label + final updatedMap = Map.from(config.labelMap!); + updatedMap.remove(labelKey); + + // Update the config + await config.updateLabelMap(newLabelMap: updatedMap, isar: mainDB); + + // Update cache + _labeledAddresses.remove(label); + } + + /// Get all Silent Payment labels for this wallet + Future> getSilentPaymentLabels() async { + final config = await _getSilentPaymentConfig(); + if (config == null || config.labelMap == null || config.labelMap!.isEmpty) { + return []; + } + + // We need to regenerate the numeric labels from the stored label data + // This is a brute force approach but works for reasonable numbers of labels + final labelMap = config.labelMap!; + final owner = await _getSilentPaymentOwner(); + final G = ECPublicKey(ECCurve_secp256k1().G.getEncoded(true)); + + final labels = []; + for (int i = 0; i < 1000; i++) { + // Arbitrary limit + final generatedLabel = owner.generateLabel(i); + final labelKey = bytesToHex(tweakMulPublic(G, generatedLabel)); + + if (labelMap.containsKey(labelKey)) { + labels.add(i); + } + } + + return labels; + } + + // Helper method to get the wallet's SilentPaymentOwner + Future _getSilentPaymentOwner() async { + if (_silentPaymentOwner != null) { + return _silentPaymentOwner!; + } + + final rootNode = await getRootHDNode(); + _silentPaymentOwner = SilentPaymentOwner.fromBip32(rootNode); + + return _silentPaymentOwner!; + } + + // Helper method to get the SilentPaymentConfig + Future _getSilentPaymentConfig() async { + return mainDB.isar.silentPaymentConfig + .where() + .walletIdEqualTo(walletId) + .findFirst(); + } + + // Helper method to get the network string in the format expected by SilentPayments + String _getNetworkString() { + switch (info.coin.network) { + case CryptoCurrencyNetwork.main: + return 'BitcoinNetwork.mainnet'; + case CryptoCurrencyNetwork.test: + case CryptoCurrencyNetwork.test4: + return 'BitcoinNetwork.testnet'; + default: + return 'BitcoinNetwork.regtest'; + } + } +} From e5d8ef737b2b2d95fa96925b2a1dac8181ed889c Mon Sep 17 00:00:00 2001 From: kent-3 <100624004+kent-3@users.noreply.github.com> Date: Fri, 9 May 2025 15:52:23 -0400 Subject: [PATCH 14/14] wip: incorporating silentium api --- .../silent_payments/silent_payments_view.dart | 127 ++++++++++-------- lib/services/silentium_api.dart | 65 +++++++++ 2 files changed, 133 insertions(+), 59 deletions(-) create mode 100644 lib/services/silentium_api.dart diff --git a/lib/pages/silent_payments/silent_payments_view.dart b/lib/pages/silent_payments/silent_payments_view.dart index 7c73ec4ce..0b39932d7 100644 --- a/lib/pages/silent_payments/silent_payments_view.dart +++ b/lib/pages/silent_payments/silent_payments_view.dart @@ -17,6 +17,7 @@ import '../../providers/silent_payment/silent_payment_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../notifications/show_flush_bar.dart'; +import '../../services/silentium_api.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; import '../../utilities/extensions/extensions.dart'; @@ -192,6 +193,12 @@ class _SilentPaymentsViewState extends ConsumerState { // Amount in satoshis final satoshiAmount = (double.parse(amount) * 100000000).toInt(); + final silentium = SilentiumApi(baseUrl: "https://bitcoin.silentium.dev/"); + final chainTip = await silentium.getLatestBlockHeight(); + final scalars = await silentium.getScalarsForBlock(883586); + + // might not need any of this here + // Get available UTXOs // final isar = mainDB.isar; // final utxos = @@ -200,65 +207,65 @@ class _SilentPaymentsViewState extends ConsumerState { // .walletIdEqualTo(widget.walletId) // .usedEqualTo(false) // .findAll(); - final utxos = - await mainDB - .getUTXOs(widget.walletId) - .filter() - .usedEqualTo(false) - .findAll(); - - final signingData = await wallet.fetchBuildTxData(utxos); - - final selectedUtxos = []; - int runningTotal = 0; - final int estimatedFee = 1000; - - for (final utxo in utxos) { - selectedUtxos.add(utxo); - runningTotal += utxo.value; - - if (runningTotal >= satoshiAmount + estimatedFee) { - break; - } - } - - // Convert UTXOs to outpoints - final outpoints = - selectedUtxos.map((utxo) { - return OutPoint(utxo.txid.toUint8ListFromHex, utxo.vout); - }).toList(); - - final inputPrivateInfos = - selectedUtxos.map((utxo) async { - // TODO: figure out how to get private key for each outpoint - final address = await mainDB.getAddress( - wallet.walletId, - utxo.address!, - ); - final keys = root.derivePath(address.derivationPath!.value); - final ECPrivateKey privkey; - final bool isTaproot; - return ECPrivateInfo(privkey, isTaproot); - }).toList(); - - // Prepare destination addresses - final destinations = [ - SilentPaymentDestination.fromAddress(recipientAddress, 0), - ]; - - final inputPubKeys = - inputPrivateInfos.map((info) => info.privkey.pubkey).toList(); - - final builder = SilentPaymentBuilder( - outpoints: outpoints, - publicKeys: inputPubKeys, - ); - - final outputMap = builder.createOutputs(inputPrivateInfos, destinations); - final sendingOutputs = - outputMap.values - .expand((outputs) => outputs.map((o) => o.address.data.toHex)) - .toList(); + // final utxos = + // await mainDB + // .getUTXOs(widget.walletId) + // .filter() + // .usedEqualTo(false) + // .findAll(); + // + // final signingData = await wallet.fetchBuildTxData(utxos); + // + // final selectedUtxos = []; + // int runningTotal = 0; + // final int estimatedFee = 1000; + // + // for (final utxo in utxos) { + // selectedUtxos.add(utxo); + // runningTotal += utxo.value; + // + // if (runningTotal >= satoshiAmount + estimatedFee) { + // break; + // } + // } + // + // // Convert UTXOs to outpoints + // final outpoints = + // selectedUtxos.map((utxo) { + // return OutPoint(utxo.txid.toUint8ListFromHex, utxo.vout); + // }).toList(); + // + // final inputPrivateInfos = + // selectedUtxos.map((utxo) async { + // // TODO: figure out how to get private key for each outpoint + // final address = await mainDB.getAddress( + // wallet.walletId, + // utxo.address!, + // ); + // final keys = root.derivePath(address.derivationPath!.value); + // final ECPrivateKey privkey; + // final bool isTaproot; + // return ECPrivateInfo(privkey, isTaproot); + // }).toList(); + // + // // Prepare destination addresses + // final destinations = [ + // SilentPaymentDestination.fromAddress(recipientAddress, 0), + // ]; + // + // final inputPubKeys = + // inputPrivateInfos.map((info) => info.privkey.pubkey).toList(); + // + // final builder = SilentPaymentBuilder( + // outpoints: outpoints, + // publicKeys: inputPubKeys, + // ); + // + // final outputMap = builder.createOutputs(inputPrivateInfos, destinations); + // final sendingOutputs = + // outputMap.values + // .expand((outputs) => outputs.map((o) => o.address.data.toHex)) + // .toList(); await Future.delayed(const Duration(seconds: 1)); @@ -285,6 +292,8 @@ class _SilentPaymentsViewState extends ConsumerState { "Amount": "$amount BTC", "Transaction ID": txDetails["txid"]! as String, "Output Addresses": (txDetails["outputs"] as List).join("\n"), + "Chain Tip": chainTip.toString(), + "Scalars": scalars.join("\n"), }); if (mounted) { diff --git a/lib/services/silentium_api.dart b/lib/services/silentium_api.dart new file mode 100644 index 000000000..5042e8ee0 --- /dev/null +++ b/lib/services/silentium_api.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +/// Service for interacting with the Silentium API +class SilentiumApi { + final String baseUrl; + final http.Client _client; + + SilentiumApi({required this.baseUrl, http.Client? client}) + : _client = client ?? http.Client(); + + /// Close the HTTP client when done + void dispose() { + _client.close(); + } + + /// Get the latest block height from the chain tip + Future getLatestBlockHeight() async { + final response = await _client.get( + Uri.parse('$baseUrl/v1/chain/tip'), + headers: {'Content-Type': 'application/json'}, + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body) as Map; + return data['height'] as int; + } else { + throw Exception( + 'Failed to get latest block height: ${response.statusCode}', + ); + } + } + + /// Get scalars for a specific block height + /// Returns a list of scalar hex strings + Future> getScalarsForBlock(int height) async { + final response = await _client.get( + Uri.parse('$baseUrl/v1/block/$height/scalars'), + headers: {'Content-Type': 'application/json'}, + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body) as Map; + return List.from(data['scalars'] as List); + } else if (response.statusCode == 404) { + // Block not found or no scalars available + return []; + } else { + throw Exception('Failed to get scalars: ${response.statusCode}'); + } + } + + /// Ping the API to check if it's available + Future isAvailable() async { + try { + final response = await _client.get( + Uri.parse('$baseUrl/v1/chain/tip'), + headers: {'Content-Type': 'application/json'}, + ); + return response.statusCode == 200; + } catch (e) { + return false; + } + } +}