Initial peyawallet import with monero_c submodule

This commit is contained in:
Codex Bot
2026-04-06 20:58:42 +02:00
commit 888798cabe
77 changed files with 14696 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
import 'dart:convert';
import 'dart:io';
import 'package:logger/logger.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import '../domain/models.dart';
class ConfigRepository {
ConfigRepository(this._configFile, this._logger);
final File _configFile;
final Logger _logger;
static Future<ConfigRepository> create(Logger logger) async {
final baseDir = await getApplicationSupportDirectory();
final configDir = Directory(baseDir.path);
if (!await configDir.exists()) {
await configDir.create(recursive: true);
}
final configFile = File(p.join(configDir.path, 'config.json'));
return ConfigRepository(configFile, logger);
}
File get configFile => _configFile;
Future<AppConfig> loadConfig() async {
if (!await _configFile.exists()) {
_logger.i('Config not found, using defaults.');
return AppConfig.defaults();
}
try {
final contents = await _configFile.readAsString();
return AppConfig.fromJson(_decode(contents));
} catch (error, stack) {
_logger.e('Failed to load config, using defaults.', error: error, stackTrace: stack);
return AppConfig.defaults();
}
}
Future<void> saveConfig(AppConfig config) async {
try {
await _configFile.writeAsString(AppConfig.prettyPrint(config));
_logger.i('Config saved to ${_configFile.path}');
} catch (error, stack) {
_logger.e('Failed to save config', error: error, stackTrace: stack);
}
}
Map<String, dynamic> _decode(String raw) {
final json = raw.trim().isEmpty ? '{}' : raw;
return json.isEmpty ? <String, dynamic>{} : (jsonDecode(json) as Map<String, dynamic>);
}
}
+17
View File
@@ -0,0 +1,17 @@
import '../domain/models.dart';
import 'config_repository.dart';
class NodeRepository {
NodeRepository(this._configRepository);
final ConfigRepository _configRepository;
Future<NodeConfig> loadNodeConfig() async {
final config = await _configRepository.loadConfig();
return config.nodeConfig;
}
Future<void> saveNodeConfig(AppConfig config, NodeConfig nodeConfig) async {
await _configRepository.saveConfig(config.copyWith(nodeConfig: nodeConfig));
}
}
+12
View File
@@ -0,0 +1,12 @@
import '../domain/models.dart';
import 'config_repository.dart';
class SettingsRepository {
SettingsRepository(this._configRepository);
final ConfigRepository _configRepository;
Future<AppConfig> loadSettings() => _configRepository.loadConfig();
Future<void> saveSettings(AppConfig config) => _configRepository.saveConfig(config);
}
+168
View File
@@ -0,0 +1,168 @@
import '../domain/models.dart';
import '../domain/send.dart';
import '../domain/transactions.dart';
import '../native/wallet_backend.dart';
class WalletSnapshot {
const WalletSnapshot({
required this.address,
required this.balanceAtomic,
required this.unlockedAtomic,
required this.nodeHeight,
required this.walletHeight,
required this.synced,
required this.progress,
required this.subaddresses,
});
final String address;
final int balanceAtomic;
final int unlockedAtomic;
final int nodeHeight;
final int walletHeight;
final bool synced;
final double progress;
final List<SubaddressInfo> subaddresses;
}
class WalletRepository {
WalletRepository(this._backend);
final WalletBackend _backend;
Future<void> _operationQueue = Future.value();
int get maxDestinations => _backend.maxDestinations;
Future<T> _runLocked<T>(Future<T> Function() action) {
final next = _operationQueue.then((_) => action());
_operationQueue = next.then((_) => null, onError: (_) => null);
return next;
}
Future<void> createWallet({
required String name,
required String path,
required String password,
}) {
return _runLocked(() {
return _backend.createWallet(name: name, path: path, password: password);
});
}
Future<void> restoreWalletFromSeed({
required String name,
required String seed,
required String path,
required String password,
}) {
return _runLocked(() {
return _backend.restoreWalletFromSeed(
name: name,
seed: seed,
path: path,
password: password,
);
});
}
Future<void> openWallet({
required String path,
required String password,
}) {
return _runLocked(() {
return _backend.openWallet(path: path, password: password);
});
}
Future<void> closeWallet() {
return _runLocked(() => _backend.closeWallet());
}
Future<String> getAddress() {
return _runLocked(() => _backend.getAddress());
}
Future<String> getSeed() {
return _runLocked(() => _backend.getSeed());
}
Future<List<WalletTransaction>> getTransactions() {
return _runLocked(() => _backend.getTransactions());
}
Future<bool> isConnected() {
return _runLocked(() => _backend.isConnected());
}
Future<String> createSubaddress({String? label}) {
return _runLocked(() => _backend.createSubaddress(label: label));
}
Future<List<SubaddressInfo>> getSubaddresses() {
return _runLocked(() => _backend.getSubaddresses());
}
Future<void> setSubaddressLabel({
required int accountIndex,
required int addressIndex,
required String label,
}) {
return _runLocked(() {
return _backend.setSubaddressLabel(
accountIndex: accountIndex,
addressIndex: addressIndex,
label: label,
);
});
}
Future<SendPreview> prepareSend(SendRequest request) {
return _runLocked(() => _backend.prepareSend(request));
}
Future<SendResult> commitPreparedSend() {
return _runLocked(() => _backend.commitPreparedSend());
}
Future<void> discardPreparedSend() {
return _runLocked(() => _backend.discardPreparedSend());
}
Future<void> connectNode(NodeConfig nodeConfig) {
return _runLocked(() => _backend.connectToNode(nodeConfig));
}
Future<WalletSnapshot> refresh() async {
return _runLocked(() async {
await _backend.refresh();
final address = await _backend.getAddress();
final balance = await _backend.getBalance();
final unlockedBalance = await _backend.getUnlockedBalance();
final nodeHeight = await _backend.getNodeHeight();
final walletHeight = await _backend.getWalletHeight();
final synced = await _backend.isSynced();
final progress = await _backend.getSyncProgress();
List<SubaddressInfo> subaddresses;
try {
subaddresses = await _backend.getSubaddresses();
} catch (_) {
subaddresses = const [];
}
return WalletSnapshot(
address: address,
balanceAtomic: balance,
unlockedAtomic: unlockedBalance,
nodeHeight: nodeHeight,
walletHeight: walletHeight,
synced: synced,
progress: progress,
subaddresses: subaddresses,
);
});
}
Future<void> rescanBlockchain({int? fromHeight}) {
return _runLocked(() => _backend.rescanBlockchain(fromHeight: fromHeight));
}
}