Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions lib/features/settings/providers/nwc_provider.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';

// Sentinel for copyWith nullable fields.
const _unset = Object();

/// SharedPreferences key for the persisted NWC URI.
const kNwcUriKey = 'settings.nwcUri';

/// Wallet connection state held in memory.
///
/// `null` → no wallet connected.
Expand Down Expand Up @@ -40,13 +44,24 @@ class NwcWalletState {
// ── Notifier ───────────────────────────────────────────────────────────────────

class NwcNotifier extends StateNotifier<NwcWalletState?> {
NwcNotifier() : super(null);
NwcNotifier({SharedPreferences? prefs}) : _prefs = prefs, super(null);

final SharedPreferences? _prefs;

/// Store wallet state after a successful `connect_wallet` call.
void setConnected(NwcWalletState wallet) => state = wallet;
/// Persists the NWC URI so it survives app restarts.
void setConnected(NwcWalletState wallet, {String? nwcUri}) {
state = wallet;
if (nwcUri != null) {
_prefs?.setString(kNwcUriKey, nwcUri);
}
}

/// Clear wallet state after `disconnect_wallet`.
void setDisconnected() => state = null;
void setDisconnected() {
state = null;
_prefs?.remove(kNwcUriKey);
}

/// Update balance from a `get_balance` result.
void updateBalance(int? sats) {
Expand All @@ -59,6 +74,7 @@ class NwcNotifier extends StateNotifier<NwcWalletState?> {
// ── Providers ─────────────────────────────────────────────────────────────────

/// Wallet connection state. `null` when no wallet is connected.
/// Override in `main()` via [ProviderScope] to inject [SharedPreferences].
final nwcProvider =
StateNotifierProvider<NwcNotifier, NwcWalletState?>((ref) => NwcNotifier());

Expand Down
1 change: 1 addition & 0 deletions lib/features/settings/screens/connect_wallet_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class _ConnectWalletScreenState extends ConsumerState<ConnectWalletScreen> {
walletName: info.walletName,
balanceSats: info.balanceSats?.toInt(),
),
nwcUri: _uriController.text.trim(),
);
context.go(AppRoute.walletSettings);
} catch (e) {
Expand Down
5 changes: 5 additions & 0 deletions lib/features/settings/screens/settings_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).settingsScreenTitle),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () =>
context.canPop() ? context.pop() : context.go(AppRoute.home),
),
),
body: ListView(
padding: const EdgeInsets.all(AppSpacing.lg),
Expand Down
9 changes: 8 additions & 1 deletion lib/features/settings/screens/wallet_settings_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ class WalletSettingsScreen extends ConsumerWidget {
final cardBg = colors?.backgroundCard ?? const Color(0xFF1E2230);

return Scaffold(
appBar: AppBar(title: const Text('Wallet Configuration')),
appBar: AppBar(
title: const Text('Wallet Configuration'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () =>
context.canPop() ? context.pop() : context.go(AppRoute.settings),
),
),
body: Padding(
padding: const EdgeInsets.all(AppSpacing.lg),
child: wallet == null
Expand Down
37 changes: 36 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import 'package:mostro/features/walkthrough/providers/first_run_provider.dart';
import 'package:mostro/features/account/providers/backup_reminder_provider.dart';
import 'package:mostro/src/rust/frb_generated.dart';
import 'package:mostro/src/rust/api.dart' as rust_api;
import 'package:mostro/features/settings/providers/nwc_provider.dart';
import 'package:mostro/src/rust/api/nwc.dart' as nwc_api;
import 'package:mostro/src/rust/api/nostr.dart' as nostr_api;
import 'package:mostro/src/rust/api/orders.dart' as orders_api;

Expand Down Expand Up @@ -58,7 +60,7 @@ Future<void> main() async {
// Watch for connection state changes in background (logs appear in flutter output).
_watchConnectionState();

runApp(ProviderScope(
final container = ProviderContainer(
overrides: [
firstRunProvider.overrideWith(
(ref) => FirstRunNotifier(initialValue: firstRunComplete),
Expand All @@ -69,11 +71,44 @@ Future<void> main() async {
settingsProvider.overrideWith(
(ref) => SettingsNotifier(prefs: prefs, initial: savedSettings),
),
nwcProvider.overrideWith(
(ref) => NwcNotifier(prefs: prefs),
),
],
);

// Restore NWC wallet connection if a URI was saved from a previous session.
final savedNwcUri = prefs.getString(kNwcUriKey);
if (savedNwcUri != null) {
_restoreNwcConnection(savedNwcUri, container);
}

runApp(UncontrolledProviderScope(
container: container,
child: const MostroApp(),
));
}

/// Reconnect a previously saved NWC wallet in the background.
void _restoreNwcConnection(String nwcUri, ProviderContainer container) {
Future.microtask(() async {
try {
final info = await nwc_api.connectWallet(nwcUri: nwcUri);
container.read(nwcProvider.notifier).setConnected(
NwcWalletState(
walletPubkey: info.walletPubkey,
relayUrls: info.relayUrls,
walletName: info.walletName,
balanceSats: info.balanceSats?.toInt(),
),
);
debugPrint('[nwc] wallet restored: ${info.walletName ?? info.walletPubkey}');
} catch (e) {
debugPrint('[nwc] wallet restore failed: $e');
}
});
}

/// Guards against overlapping diagnostic order polls on rapid reconnects.
bool _isPollingOrders = false;

Expand Down
12 changes: 12 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ crate-type = ["cdylib", "staticlib"]
flutter_rust_bridge = "=2.11.1"

# Nostr & Mostro protocol
nostr-sdk = { version = "0.44", default-features = false, features = ["nip44", "nip59"] }
nostr-sdk = { version = "0.44", default-features = false, features = ["nip44", "nip47", "nip59"] }
mostro-core = "0.8.0"

# Serialization
Expand Down
Loading