-
Notifications
You must be signed in to change notification settings - Fork 3
Wallet interface #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Wallet interface #134
Changes from 19 commits
1020f28
2c9c78c
bcc503a
610a5e6
d65d3de
e02dc68
b2ad177
0659823
13540e8
ae830e8
ae29d9f
dbda488
3731128
353d1f0
a48eac4
806441e
db65476
4997ead
8137b73
41abf45
fea2619
d94e931
602f9d0
8b8c9b0
b700dbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import 'dart:async'; | ||
|
|
||
| abstract class Command<T> { | ||
| String get name; | ||
| String get description; | ||
| FutureOr<T> execute(List<String> args); | ||
| } | ||
|
|
||
| class CommandResult<T> { | ||
| final bool success; | ||
| final T? data; | ||
| final String? error; | ||
|
|
||
| CommandResult.success(this.data) | ||
| : success = true, | ||
| error = null; | ||
| CommandResult.failure(this.error) | ||
| : success = false, | ||
| data = null; | ||
|
|
||
| @override | ||
| String toString() { | ||
| if (success) { | ||
| return data?.toString() ?? 'Command completed successfully'; | ||
| } else { | ||
| return 'Error: ${error ?? "Unknown error"}'; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| class CommandRegistry { | ||
| final Map<String, Command> _commands = {}; | ||
|
|
||
| void register(Command command) { | ||
| _commands[command.name.toLowerCase()] = command; | ||
| } | ||
|
|
||
| Command? get(String name) { | ||
| return _commands[name.toLowerCase()]; | ||
| } | ||
|
|
||
| List<Command> get commands => _commands.values.toList(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,38 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import 'dart:io'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import 'command.dart'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class HelpCommand extends Command<String> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| final CommandRegistry registry; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HelpCommand(this.registry); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String get name => 'help'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String get description => 'Show available commands'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String execute(List<String> args) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| final buffer = StringBuffer('Available commands:\n'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (final command in registry.commands) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| buffer.writeln(' ${command.name.padRight(10)} - ${command.description}'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return buffer.toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class ExitCommand extends Command<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String get name => 'exit'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String get description => 'Exit the application'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Future<void> execute(List<String> args) async { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print('Goodbye!'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit(0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Implement graceful shutdown. The @override
Future<void> execute(List<String> args) async {
print('Goodbye!');
- exit(0);
+ // Signal the application to start cleanup
+ return Future.value();
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,105 @@ | ||||||||||||
| import 'dart:convert'; | ||||||||||||
| import 'dart:io'; | ||||||||||||
|
|
||||||||||||
|
Comment on lines
+2
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add necessary wallet-related imports and error handling. As this is a wallet interface implementation, the file should import the necessary wallet-related modules and implement proper error handling for I/O operations. Consider adding: import 'dart:io';
+import 'package:walletkit_dart/walletkit_dart.dart';
+import 'dart:async';📝 Committable suggestion
Suggested change
|
||||||||||||
| import 'command.dart'; | ||||||||||||
| import 'commands.dart'; | ||||||||||||
|
|
||||||||||||
| class WalletCLI { | ||||||||||||
| final CommandRegistry registry = CommandRegistry(); | ||||||||||||
| final String prompt = 'wk> '; | ||||||||||||
|
|
||||||||||||
| WalletCLI() { | ||||||||||||
| registry.register(ExitCommand()); | ||||||||||||
| registry.register(HelpCommand(registry)); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // Custom print function that adds the prompt | ||||||||||||
| void printWithPrompt(String message, {bool withPrompt = true}) { | ||||||||||||
| // Split message into lines and add prompt to each line | ||||||||||||
| final lines = message.split('\n'); | ||||||||||||
| for (final line in lines) { | ||||||||||||
| if (withPrompt) { | ||||||||||||
| stdout.writeln('$prompt$line'); | ||||||||||||
| } else { | ||||||||||||
| stdout.writeln(line); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| void showPrompt() { | ||||||||||||
| stdout.write(prompt); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| Future<void> run() async { | ||||||||||||
| printWithPrompt('Welcome to WalletkitDart CLI'); | ||||||||||||
| printWithPrompt('Type "help" for available commands'); | ||||||||||||
| printWithPrompt('Enter commands:'); | ||||||||||||
| showPrompt(); | ||||||||||||
|
|
||||||||||||
| final inputStream = stdin | ||||||||||||
| .transform(utf8.decoder) | ||||||||||||
| .transform(const LineSplitter()) | ||||||||||||
| .asBroadcastStream(); | ||||||||||||
|
|
||||||||||||
|
Comment on lines
+39
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implement stream subscription cleanup. The broadcast stream subscription should be stored and cleaned up when the CLI is terminated. + StreamSubscription<String>? _inputSubscription;
+
Future<void> run() async {
// ... existing code ...
- inputStream.listen(
+ _inputSubscription = inputStream.listen(
// ... existing code ...
);
}
+ Future<void> cleanup() async {
+ await _inputSubscription?.cancel();
+ _inputSubscription = null;
+ }
|
||||||||||||
| inputStream.listen( | ||||||||||||
| (String line) async { | ||||||||||||
| await handleInput(line.trim()); | ||||||||||||
| }, | ||||||||||||
| onError: (error) { | ||||||||||||
| printWithPrompt('Error reading input: $error'); | ||||||||||||
| showPrompt(); | ||||||||||||
| }, | ||||||||||||
| onDone: () { | ||||||||||||
| printWithPrompt('Input stream closed'); | ||||||||||||
| exit(0); | ||||||||||||
| }, | ||||||||||||
| ); | ||||||||||||
|
|
||||||||||||
| startPeriodicTask(); | ||||||||||||
|
|
||||||||||||
| await Future.delayed(Duration.zero); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| Future<void> handleInput(String input) async { | ||||||||||||
| if (input.isEmpty) { | ||||||||||||
| showPrompt(); | ||||||||||||
| return; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| final parts = input.split(' '); | ||||||||||||
| final commandName = parts[0].toLowerCase(); | ||||||||||||
| final args = parts.skip(1).toList(); | ||||||||||||
|
|
||||||||||||
| final command = registry.get(commandName); | ||||||||||||
| if (command == null) { | ||||||||||||
| printWithPrompt('Unknown command: $commandName'); | ||||||||||||
| printWithPrompt('Type "help" for available commands'); | ||||||||||||
| showPrompt(); | ||||||||||||
| return; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| try { | ||||||||||||
| final result = await command.execute(args); | ||||||||||||
| if (result != null) { | ||||||||||||
| printWithPrompt(result.toString()); | ||||||||||||
| } | ||||||||||||
| showPrompt(); | ||||||||||||
| } catch (e) { | ||||||||||||
| printWithPrompt('Error executing command: $e'); | ||||||||||||
| showPrompt(); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| void startPeriodicTask() { | ||||||||||||
| /// TODO: Start Wallet sync based on args | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| void registerCommand(Command command) { | ||||||||||||
| registry.register(command); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| void main() async { | ||||||||||||
| final app = WalletCLI(); | ||||||||||||
| await app.run(); | ||||||||||||
| } | ||||||||||||
|
Comment on lines
+102
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add signal handling for graceful shutdown. Implement signal handling to ensure proper cleanup when the application is terminated. void main() async {
final app = WalletCLI();
+ ProcessSignal.sigint.watch().listen((_) async {
+ print('\nReceived SIGINT, shutting down...');
+ await app.cleanup();
+ exit(0);
+ });
await app.run();
}
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add duplicate command name validation.
The
registermethod should check for existing commands with the same name (case-insensitive) to prevent overwriting.void register(Command command) { + ArgumentError.checkNotNull(command, 'command'); + final normalizedName = command.name.toLowerCase(); + if (_commands.containsKey(normalizedName)) { + throw ArgumentError('Command "${command.name}" is already registered'); + } - _commands[command.name.toLowerCase()] = command; + _commands[normalizedName] = command; }📝 Committable suggestion