Skip to content

Commit

Permalink
Use layered folder structure
Browse files Browse the repository at this point in the history
  • Loading branch information
cygnet3 committed Jun 13, 2024
1 parent d05c418 commit 19b1168
Show file tree
Hide file tree
Showing 20 changed files with 498 additions and 267 deletions.
2 changes: 1 addition & 1 deletion flutter_rust_bridge.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
rust_input: rust/src/api/**/*.rs
dart_output: lib/rust
dart_output: lib/generated/rust
32 changes: 32 additions & 0 deletions lib/application/synchronization_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dart:async';
import 'package:donationwallet/generated/rust/api/simple.dart';
import 'package:donationwallet/utils/global_functions.dart';

class SynchronizationService {
Timer? _timer;
final Duration _interval = const Duration(minutes: 10);

void startSyncTimer() {
_scheduleNextTask();
}

void _scheduleNextTask() async {
_timer?.cancel();
await performSynchronizationTask();
_timer = Timer(_interval, () async {
_scheduleNextTask();
});
}

Future<void> performSynchronizationTask() async {
try {
await syncBlockchain();
} catch (e) {
displayNotification(e.toString());
}
}

void stopSyncTimer() {
_timer?.cancel();
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions lib/home.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'dart:async';

import 'package:bitcoin_ui/bitcoin_ui.dart';
import 'package:donationwallet/load_wallet.dart';
import 'package:donationwallet/main.dart';
import 'package:donationwallet/wallet.dart';
import 'package:donationwallet/settings.dart';
import 'package:donationwallet/presentation/features/intro/load_wallet.dart';
import 'package:donationwallet/presentation/features/wallet/wallet.dart';
import 'package:donationwallet/presentation/features/settings/settings.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

Expand Down
246 changes: 3 additions & 243 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,252 +1,12 @@
import 'dart:async';
import 'package:bitcoin_ui/bitcoin_ui.dart';
import 'package:donationwallet/rust/api/simple.dart';
import 'package:donationwallet/rust/frb_generated.dart';
import 'package:donationwallet/rust/logger.dart';
import 'package:donationwallet/generated/rust/frb_generated.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';

import 'package:donationwallet/global_functions.dart';
import 'package:donationwallet/utils/global_functions.dart';
import 'package:donationwallet/home.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:provider/provider.dart';

class SynchronizationService {
Timer? _timer;
final Duration _interval = const Duration(minutes: 10);

void startSyncTimer() {
_scheduleNextTask();
}

void _scheduleNextTask() async {
_timer?.cancel();
await performSynchronizationTask();
_timer = Timer(_interval, () async {
_scheduleNextTask();
});
}

Future<void> performSynchronizationTask() async {
try {
await syncBlockchain();
} catch (e) {
displayNotification(e.toString());
}
}

void stopSyncTimer() {
_timer?.cancel();
}
}

class WalletState extends ChangeNotifier {
final String label = "default";
BigInt amount = BigInt.from(0);
int birthday = 0;
int lastScan = 0;
int tip = 0;
double progress = 0.0;
bool scanning = false;
String network = 'signet';
bool walletLoaded = false;
String address = "";
Map<String, OwnedOutput> ownedOutputs = {};
Map<String, OwnedOutput> selectedOutputs = {};
List<Recipient> recipients = List.empty(growable: true);
final secureStorage = const FlutterSecureStorage();

late StreamSubscription logStreamSubscription;
late StreamSubscription scanProgressSubscription;
late StreamSubscription amountStreamSubscription;
late StreamSubscription syncStreamSubscription;

final _synchronizationService = SynchronizationService();

WalletState();

Future<void> initialize() async {
try {
await _initStreams();
_synchronizationService.startSyncTimer();
} catch (e) {
rethrow;
}
}

Future<void> _initStreams() async {
logStreamSubscription =
createLogStream(level: LogLevel.debug, logDependencies: true)
.listen((event) {
print('${event.level} (${event.tag}): ${event.msg}');
notifyListeners();
});

scanProgressSubscription = createScanProgressStream().listen(((event) {
int start = event.start;
int current = event.current;
int end = event.end;
double scanned = (current - start).toDouble();
double total = (end - start).toDouble();
double progress = scanned / total;
if (current == end) {
progress = 0.0;
scanning = false;
}
this.progress = progress;
lastScan = current;

notifyListeners();
}));

syncStreamSubscription = createSyncStream().listen((event) {
tip = event.blockheight;

print('tip: $tip');

notifyListeners();
});

amountStreamSubscription = createAmountStream().listen((event) {
amount = event;
notifyListeners();
});
}

@override
void dispose() {
logStreamSubscription.cancel();
scanProgressSubscription.cancel();
amountStreamSubscription.cancel();
syncStreamSubscription.cancel();
_synchronizationService.stopSyncTimer();
super.dispose();
}

Future<void> reset() async {
amount = BigInt.zero;
birthday = 0;
lastScan = 0;
progress = 0.0;
scanning = false;
walletLoaded = false;
address = "";
ownedOutputs = {};
selectedOutputs = {};
recipients = List.empty(growable: true);

notifyListeners();
}

Future<void> saveWalletToSecureStorage(String wallet) async {
await secureStorage.write(key: label, value: wallet);
}

Future<void> rmWalletFromSecureStorage() async {
await secureStorage.write(key: label, value: null);
}

Future<String> getWalletFromSecureStorage() async {
final wallet = await secureStorage.read(key: label);
if (wallet != null) {
return wallet;
} else {
throw Exception("No wallet in storage");
}
}

Future<void> updateWalletStatus() async {
WalletStatus walletInfo;
try {
final wallet = await getWalletFromSecureStorage();
walletInfo = getWalletInfo(encodedWallet: wallet);
} catch (e) {
rethrow;
}
address = walletInfo.address;
amount = walletInfo.balance;
birthday = walletInfo.birthday;
lastScan = walletInfo.lastScan;
ownedOutputs = walletInfo.outputs;
notifyListeners();
}

Map<String, OwnedOutput> getSpendableOutputs() {
var spendable = ownedOutputs.entries.where((element) =>
element.value.spendStatus == const OutputSpendStatus.unspent());
return Map.fromEntries(spendable);
}

void toggleOutputSelection(String outpoint, OwnedOutput output) {
if (selectedOutputs.containsKey(outpoint)) {
selectedOutputs.remove(outpoint);
} else {
selectedOutputs[outpoint] = output;
}
notifyListeners();
}

BigInt outputSelectionTotalAmt() {
final total = selectedOutputs.values
.fold(BigInt.zero, (sum, element) => sum + element.amount.field0);
return total;
}

BigInt recipientTotalAmt() {
final total = recipients.fold(
BigInt.zero, (sum, element) => sum + element.amount.field0);
return total;
}

Future<void> addRecipients(
String address, BigInt amount, int nbOutputs) async {
final alreadyInList = recipients.where((r) => r.address == address);
if (alreadyInList.isNotEmpty) {
throw Exception("Address already in list");
}

if (nbOutputs < 1) {
nbOutputs = 1;
}

if (amount <= BigInt.from(546)) {
throw Exception("Can't have amount inferior to 546 sats");
}
recipients.add(Recipient(
address: address,
amount: Amount(field0: amount),
nbOutputs: nbOutputs));

notifyListeners();
}

Future<void> rmRecipient(String address) async {
final alreadyInList = recipients.where((r) => r.address == address);
if (alreadyInList.isEmpty) {
throw Exception("Unknown recipient");
} else {
recipients.removeWhere((r) => r.address == address);
}
notifyListeners();
}

Future<void> scan() async {
try {
scanning = true;
await syncBlockchain();
final wallet = await getWalletFromSecureStorage();
final updatedWallet = await scanToTip(encodedWallet: wallet);
print(updatedWallet);
await saveWalletToSecureStorage(updatedWallet);
} catch (e) {
scanning = false;
notifyListeners();
rethrow;
}
scanning = false;
notifyListeners();
}
}

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await RustLib.init();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'dart:async';

import 'package:donationwallet/rust/api/simple.dart';
import 'package:donationwallet/generated/rust/api/simple.dart';
import 'package:donationwallet/home.dart';
import 'package:donationwallet/main.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
Expand Down
10 changes: 5 additions & 5 deletions lib/spend.dart → lib/presentation/features/sending/spend.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:donationwallet/rust/api/simple.dart';
import 'package:donationwallet/global_functions.dart';
import 'package:donationwallet/main.dart';
import 'package:donationwallet/outputs.dart';
import 'package:donationwallet/destination.dart';
import 'package:donationwallet/generated/rust/api/simple.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';
import 'package:donationwallet/utils/global_functions.dart';
import 'package:donationwallet/presentation/features/spend/outputs.dart';
import 'package:donationwallet/presentation/features/spend/destination.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:bitcoin_ui/bitcoin_ui.dart';
import 'package:donationwallet/rust/api/simple.dart';
import 'package:donationwallet/global_functions.dart';
import 'package:donationwallet/main.dart';
import 'package:donationwallet/generated/rust/api/simple.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';
import 'package:donationwallet/utils/global_functions.dart';
import 'package:donationwallet/home.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
Expand Down Expand Up @@ -71,9 +71,8 @@ class SettingsScreen extends StatelessWidget {
final walletState = Provider.of<WalletState>(context, listen: false);
try {
final wallet = await walletState.getWalletFromSecureStorage();
final updatedWallet = changeBirthday(
encodedWallet: wallet,
birthday: value);
final updatedWallet =
changeBirthday(encodedWallet: wallet, birthday: value);
walletState.saveWalletToSecureStorage(updatedWallet);
callback(null);
await walletState.updateWalletStatus();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:donationwallet/main.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:donationwallet/rust/api/simple.dart';
import 'package:donationwallet/generated/rust/api/simple.dart';

Future<void> _showAddRecipientDialog(
BuildContext context,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'package:donationwallet/main.dart';
import 'package:donationwallet/presentation/states/wallet_state.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:donationwallet/rust/api/simple.dart';
import 'package:donationwallet/generated/rust/api/simple.dart';

class OutputsScreen extends StatelessWidget {
const OutputsScreen({super.key});
Expand Down
Loading

0 comments on commit 19b1168

Please sign in to comment.