diff --git a/README.md b/README.md index de2eb89..117c43b 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,16 @@ Feel free to check out the smart contract used in this project [https://github.c ### Release notes +2.0.0+7: + +- Flutter has been upgraded to version 2.0.6 (dart 2.12.3) +- Handled null-safety +- Removed HDKey class [after agreed](https://github.com/alepop/dart-ed25519-hd-key/issues/5) to add master secret as optional parameter in [dart-ed25519-hd-key](https://github.com/alepop/dart-ed25519-hd-key) library. Re-added as dependency. +- Libraries has been upgraded. +- Removed discontinued [firebase_ml_vision](https://pub.dev/packages/firebase_ml_vision) in favor of [qr_code_scanner](https://pub.dev/packages/qr_code_scanner) +- Added menu option to reveal private key + + 1.3.0+6: - Flutter has been upgraded to version 2.0.1 (dart 2.12.0). diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..cb3e1af --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,228 @@ +# Specify analysis options. +# +# Until there are meta linter rules, each desired lint must be explicitly enabled. +# See: https://github.com/dart-lang/linter/issues/288 +# +# For a list of lints, see: http://dart-lang.github.io/linter/lints/ +# See the configuration guide for more +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer +# +# There are other similar analysis options files in the flutter repos, +# which should be kept in sync with this file: +# +# - analysis_options.yaml (this file) +# - packages/flutter/lib/analysis_options_user.yaml +# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml +# - https://github.com/flutter/engine/blob/master/analysis_options.yaml +# +# This file contains the analysis options used by Flutter tools, such as IntelliJ, +# Android Studio, and the `flutter analyze` command. + +analyzer: + strong-mode: + implicit-casts: false +# implicit-dynamic: false + errors: + # treat missing required parameters as a warning (not a hint) + missing_required_param: warning + # treat missing returns as a warning (not a hint) + missing_return: warning + # allow having TODOs in the code + todo: ignore + # allow self-reference to deprecated members (we do this because otherwise we have + # to annotate every member in every test, assert, etc, when we deprecate something) + deprecated_member_use_from_same_package: ignore + # Ignore analyzer hints for updating pubspecs when using Future or + # Stream and not importing dart:async + # Please see https://github.com/flutter/flutter/pull/24528 for details. + sdk_version_async_exported_from_core: ignore + # Turned off until null-safe rollout is complete. + unnecessary_null_comparison: ignore + exclude: + - "bin/cache/**" + - "**/*.g.dart" + +linter: + rules: + # these rules are documented on and in the same order as + # the Dart Lint rules page to make maintenance easier + # https://github.com/dart-lang/linter/blob/master/example/all.yaml + - always_declare_return_types + - always_put_control_body_on_new_line + # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 + - always_require_non_null_named_parameters + # - always_use_package_imports # we do this commonly + - annotate_overrides + # - avoid_annotating_with_dynamic # conflicts with always_specify_types + - avoid_bool_literals_in_conditional_expressions + # - avoid_catches_without_on_clauses # we do this commonly + # - avoid_catching_errors # we do this commonly + - avoid_classes_with_only_static_members + # - avoid_double_and_int_checks # only useful when targeting JS runtime + # - avoid_dynamic_calls # not yet tested + - avoid_empty_else + - avoid_equals_and_hash_code_on_mutable_classes + # - avoid_escaping_inner_quotes # not yet tested + - avoid_field_initializers_in_const_classes + - avoid_function_literals_in_foreach_calls + # - avoid_implementing_value_types # not yet tested + - avoid_init_to_null + # - avoid_js_rounded_ints # only useful when targeting JS runtime + - avoid_null_checks_in_equality_operators + # - avoid_positional_boolean_parameters # not yet tested + # - avoid_print # not yet tested + # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) + # - avoid_redundant_argument_values # not yet tested + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + # - avoid_returning_null # there are plenty of valid reasons to return null + # - avoid_returning_null_for_future # not yet tested + - avoid_returning_null_for_void + # - avoid_returning_this # there are plenty of valid reasons to return this + # - avoid_setters_without_getters # not yet tested + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_slow_async_io + - avoid_type_to_string + - avoid_types_as_parameter_names + # - avoid_types_on_closure_parameters # conflicts with always_specify_types + - avoid_unnecessary_containers + - avoid_unused_constructor_parameters + - avoid_void_async + # - avoid_web_libraries_in_flutter # not yet tested + - await_only_futures + - camel_case_extensions + - camel_case_types + - cancel_subscriptions + # - cascade_invocations # not yet tested + - cast_nullable_to_non_nullable + # - close_sinks # not reliable enough + # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142 + # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 + - control_flow_in_finally + # - curly_braces_in_flow_control_structures # not required by flutter style + # - diagnostic_describe_all_properties # not yet tested + - directives_ordering + # - do_not_use_environment # we do this commonly + - empty_catches + - empty_constructor_bodies + - empty_statements + - exhaustive_cases + - file_names + - flutter_style_todos + - hash_and_equals + - implementation_imports + # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 + - iterable_contains_unrelated_type + # - join_return_with_assignment # not required by flutter style + - leading_newlines_in_multiline_strings + - library_names + - library_prefixes + # - lines_longer_than_80_chars # not required by flutter style + - list_remove_unrelated_type + # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + # - no_default_cases # too many false positives + - no_duplicate_case_values + - no_logic_in_create_state + # - no_runtimeType_toString # ok in tests; we enable this only in packages/ +# - non_constant_identifier_names + - null_check_on_nullable_type_parameter + - null_closures + # - omit_local_variable_types # opposite of always_specify_types + # - one_member_abstracts # too many false positives + # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + # - parameter_assignments # we do this commonly + - prefer_adjacent_string_concatenation + - prefer_asserts_in_initializer_lists + # - prefer_asserts_with_message # not required by flutter style + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_const_constructors_in_immutables + - prefer_const_declarations + - prefer_const_literals_to_create_immutables + # - prefer_constructors_over_static_methods # far too many false positives + - prefer_contains + # - prefer_double_quotes # opposite of prefer_single_quotes + - prefer_equal_for_default_values + # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods + - prefer_final_fields + - prefer_final_in_for_each + - prefer_final_locals + - prefer_for_elements_to_map_fromIterable + - prefer_foreach + - prefer_function_declarations_over_variables + - prefer_generic_function_type_aliases + - prefer_if_elements_to_conditional_expressions + - prefer_if_null_operators + - prefer_initializing_formals + - prefer_inlined_adds + # - prefer_int_literals # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#use-double-literals-for-double-constants + # - prefer_interpolation_to_compose_strings # doesn't work with raw strings, see https://github.com/dart-lang/linter/issues/2490 + - prefer_is_empty + - prefer_is_not_empty + - prefer_is_not_operator + - prefer_iterable_whereType + # - prefer_mixin # https://github.com/dart-lang/language/issues/32 + - prefer_null_aware_operators + # - prefer_relative_imports # incompatible with sub-package imports + - prefer_single_quotes + - prefer_spread_collections + - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml + - recursive_getters + - sized_box_for_whitespace + - slash_for_doc_comments + # - sort_child_properties_last # not yet tested + - sort_constructors_first + # - sort_pub_dependencies # prevents separating pinned transitive dependencies + - sort_unnamed_constructors_first + - test_types_in_equals + - throw_in_finally + - tighten_type_of_initializing_formals + # - type_annotate_public_apis # subset of always_specify_types + - type_init_formals + # - unawaited_futures # too many false positives + - unnecessary_await_in_return + - unnecessary_brace_in_string_interps + - unnecessary_const + # - unnecessary_final # conflicts with prefer_final_locals + - unnecessary_getters_setters + # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 + - unnecessary_new + - unnecessary_null_aware_assignments + # - unnecessary_null_checks # not yet tested + - unnecessary_null_in_if_null_operators + - unnecessary_nullable_for_final_variable_declarations + - unnecessary_overrides + - unnecessary_parenthesis + # - unnecessary_raw_strings # not yet tested + - unnecessary_statements + - unnecessary_string_escapes + - unnecessary_string_interpolations + - unnecessary_this + - unrelated_type_equality_checks + # - unsafe_html # not yet tested + - use_full_hex_values_for_flutter_colors + - use_function_type_syntax_for_parameters + # - use_if_null_to_convert_nulls_to_bools # not yet tested + - use_is_even_rather_than_modulo + - use_key_in_widget_constructors + - use_late_for_private_fields_and_variables + # - use_named_constants # not yet tested + - use_raw_strings + - use_rethrow_when_possible + # - use_setters_to_change_properties # not yet tested + # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 + # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review + - valid_regexps + - void_checks \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 2dd8098..651309f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -54,8 +54,6 @@ android { } dependencies { - api 'com.google.firebase:firebase-ml-vision-image-label-model:17.0.2' - // api 'com.google.mlkit:image-labeling:17.0.2' TODO: upgrade. } } diff --git a/fonts/MyFlutterApp.ttf b/fonts/MyFlutterApp.ttf index 02ecd11..34bf517 100644 Binary files a/fonts/MyFlutterApp.ttf and b/fonts/MyFlutterApp.ttf differ diff --git a/fonts/config.json b/fonts/config.json index 02d76b0..ad2e3bb 100644 --- a/fonts/config.json +++ b/fonts/config.json @@ -23,6 +23,12 @@ "css": "skull", "code": 62796, "src": "fontawesome5" + }, + { + "uid": "71f905d8fda639701b4127de4b0bab67", + "css": "key", + "code": 61572, + "src": "fontawesome5" } ] } \ No newline at end of file diff --git a/ios/Podfile b/ios/Podfile index 0073cd4..9cf4f6f 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '10.0' +platform :ios, '10.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -28,8 +28,6 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe flutter_ios_podfile_setup target 'Runner' do - # pod 'GoogleMLKit/BarcodeScanning' - TODO: update. - pod 'Firebase/MLVisionBarcodeModel' use_frameworks! use_modular_headers! diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ce00c45..7fa2315 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,138 +1,109 @@ PODS: - - camera (0.0.1): - - Flutter - - Firebase/Analytics (6.34.0): + - Firebase/Analytics (7.11.0): - Firebase/Core - - Firebase/Core (6.34.0): - - Firebase/CoreOnly - - FirebaseAnalytics (= 6.9.0) - - Firebase/CoreOnly (6.34.0): - - FirebaseCore (= 6.10.4) - - Firebase/MLVision (6.34.0): + - Firebase/Core (7.11.0): - Firebase/CoreOnly - - FirebaseMLVision (~> 0.21.0) - - Firebase/MLVisionBarcodeModel (6.34.0): - - Firebase/CoreOnly - - FirebaseMLVisionBarcodeModel (~> 0.21.0) - - firebase_analytics (0.0.1): - - Firebase/Analytics (~> 6.0) - - Firebase/Core + - FirebaseAnalytics (~> 7.11.0) + - Firebase/CoreOnly (7.11.0): + - FirebaseCore (= 7.11.0) + - firebase_analytics (8.0.4): + - Firebase/Analytics (= 7.11.0) + - firebase_core - Flutter - - firebase_ml_vision (0.1.1): - - Firebase/Core - - Firebase/MLVision + - firebase_core (1.1.1): + - Firebase/CoreOnly (= 7.11.0) - Flutter - - FirebaseAnalytics (6.9.0): - - FirebaseCore (~> 6.10) - - FirebaseInstallations (~> 1.7) - - GoogleAppMeasurement (= 6.9.0) - - GoogleUtilities/AppDelegateSwizzler (~> 6.7) - - GoogleUtilities/MethodSwizzler (~> 6.7) - - GoogleUtilities/Network (~> 6.7) - - "GoogleUtilities/NSData+zlib (~> 6.7)" - - nanopb (~> 1.30906.0) - - FirebaseCore (6.10.4): - - FirebaseCoreDiagnostics (~> 1.6) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/Logger (~> 6.7) - - FirebaseCoreDiagnostics (1.7.0): - - GoogleDataTransport (~> 7.4) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/Logger (~> 6.7) - - nanopb (~> 1.30906.0) - - FirebaseInstallations (1.7.0): - - FirebaseCore (~> 6.10) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/UserDefaults (~> 6.7) + - FirebaseAnalytics (7.11.0): + - FirebaseAnalytics/AdIdSupport (= 7.11.0) + - FirebaseCore (~> 7.0) + - FirebaseInstallations (~> 7.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.0) + - GoogleUtilities/MethodSwizzler (~> 7.0) + - GoogleUtilities/Network (~> 7.0) + - "GoogleUtilities/NSData+zlib (~> 7.0)" + - nanopb (~> 2.30908.0) + - FirebaseAnalytics/AdIdSupport (7.11.0): + - FirebaseAnalytics/Base (= 7.11.0) + - FirebaseCore (~> 7.0) + - FirebaseInstallations (~> 7.0) + - GoogleAppMeasurement/AdIdSupport (= 7.11.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.0) + - GoogleUtilities/MethodSwizzler (~> 7.0) + - GoogleUtilities/Network (~> 7.0) + - "GoogleUtilities/NSData+zlib (~> 7.0)" + - nanopb (~> 2.30908.0) + - FirebaseAnalytics/Base (7.11.0): + - FirebaseCore (~> 7.0) + - FirebaseInstallations (~> 7.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.0) + - GoogleUtilities/MethodSwizzler (~> 7.0) + - GoogleUtilities/Network (~> 7.0) + - "GoogleUtilities/NSData+zlib (~> 7.0)" + - nanopb (~> 2.30908.0) + - FirebaseCore (7.11.0): + - FirebaseCoreDiagnostics (~> 7.4) + - GoogleUtilities/Environment (~> 7.0) + - GoogleUtilities/Logger (~> 7.0) + - FirebaseCoreDiagnostics (7.11.0): + - GoogleDataTransport (~> 8.4) + - GoogleUtilities/Environment (~> 7.0) + - GoogleUtilities/Logger (~> 7.0) + - nanopb (~> 2.30908.0) + - FirebaseInstallations (7.11.0): + - FirebaseCore (~> 7.0) + - GoogleUtilities/Environment (~> 7.0) + - GoogleUtilities/UserDefaults (~> 7.0) - PromisesObjC (~> 1.2) - - FirebaseMLCommon (0.21.0): - - FirebaseCore (~> 6.9) - - FirebaseInstallations (~> 1.5) - - GoogleToolboxForMac/Logger (~> 2.1) - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" - - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)" - - GoogleUtilities/UserDefaults (~> 6.0) - - GTMSessionFetcher/Core (~> 1.1) - - Protobuf (~> 3.12) - - FirebaseMLVision (0.21.0): - - FirebaseCore (~> 6.9) - - FirebaseMLCommon (~> 0.21) - - GoogleAPIClientForREST/Core (~> 1.3) - - GoogleAPIClientForREST/Vision (~> 1.3) - - GoogleToolboxForMac/Logger (~> 2.1) - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" - - GTMSessionFetcher/Core (~> 1.1) - - Protobuf (~> 3.12) - - FirebaseMLVisionBarcodeModel (0.21.0): - - FirebaseMLVision (~> 0.21) - Flutter (1.0.0) - - GoogleAPIClientForREST/Core (1.5.1): - - GTMSessionFetcher (>= 1.1.7) - - GoogleAPIClientForREST/Vision (1.5.1): - - GoogleAPIClientForREST/Core - - GTMSessionFetcher (>= 1.1.7) - - GoogleAppMeasurement (6.9.0): - - GoogleUtilities/AppDelegateSwizzler (~> 6.7) - - GoogleUtilities/MethodSwizzler (~> 6.7) - - GoogleUtilities/Network (~> 6.7) - - "GoogleUtilities/NSData+zlib (~> 6.7)" - - nanopb (~> 1.30906.0) - - GoogleDataTransport (7.5.1): - - nanopb (~> 1.30906.0) - - GoogleToolboxForMac/DebugUtils (2.3.1): - - GoogleToolboxForMac/Defines (= 2.3.1) - - GoogleToolboxForMac/Defines (2.3.1) - - GoogleToolboxForMac/Logger (2.3.1): - - GoogleToolboxForMac/Defines (= 2.3.1) - - "GoogleToolboxForMac/NSData+zlib (2.3.1)": - - GoogleToolboxForMac/Defines (= 2.3.1) - - "GoogleToolboxForMac/NSDictionary+URLArguments (2.3.1)": - - GoogleToolboxForMac/DebugUtils (= 2.3.1) - - GoogleToolboxForMac/Defines (= 2.3.1) - - "GoogleToolboxForMac/NSString+URLArguments (= 2.3.1)" - - "GoogleToolboxForMac/NSString+URLArguments (2.3.1)" - - GoogleUtilities/AppDelegateSwizzler (6.7.2): + - GoogleAppMeasurement/AdIdSupport (7.11.0): + - GoogleUtilities/AppDelegateSwizzler (~> 7.0) + - GoogleUtilities/MethodSwizzler (~> 7.0) + - GoogleUtilities/Network (~> 7.0) + - "GoogleUtilities/NSData+zlib (~> 7.0)" + - nanopb (~> 2.30908.0) + - GoogleDataTransport (8.4.0): + - GoogleUtilities/Environment (~> 7.2) + - nanopb (~> 2.30908.0) + - PromisesObjC (~> 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.4.1): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (6.7.2): + - GoogleUtilities/Environment (7.4.1): - PromisesObjC (~> 1.2) - - GoogleUtilities/Logger (6.7.2): + - GoogleUtilities/Logger (7.4.1): - GoogleUtilities/Environment - - GoogleUtilities/MethodSwizzler (6.7.2): + - GoogleUtilities/MethodSwizzler (7.4.1): - GoogleUtilities/Logger - - GoogleUtilities/Network (6.7.2): + - GoogleUtilities/Network (7.4.1): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (6.7.2)" - - GoogleUtilities/Reachability (6.7.2): + - "GoogleUtilities/NSData+zlib (7.4.1)" + - GoogleUtilities/Reachability (7.4.1): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (6.7.2): + - GoogleUtilities/UserDefaults (7.4.1): - GoogleUtilities/Logger - - GTMSessionFetcher (1.5.0): - - GTMSessionFetcher/Full (= 1.5.0) - - GTMSessionFetcher/Core (1.5.0) - - GTMSessionFetcher/Full (1.5.0): - - GTMSessionFetcher/Core (= 1.5.0) - - nanopb (1.30906.0): - - nanopb/decode (= 1.30906.0) - - nanopb/encode (= 1.30906.0) - - nanopb/decode (1.30906.0) - - nanopb/encode (1.30906.0) + - MTBBarcodeScanner (5.0.11) + - nanopb (2.30908.0): + - nanopb/decode (= 2.30908.0) + - nanopb/encode (= 2.30908.0) + - nanopb/decode (2.30908.0) + - nanopb/encode (2.30908.0) - PromisesObjC (1.2.12) - - Protobuf (3.14.0) + - qr_code_scanner (0.2.0): + - Flutter + - MTBBarcodeScanner - shared_preferences (0.0.1): - Flutter - url_launcher (0.0.1): - Flutter DEPENDENCIES: - - camera (from `.symlinks/plugins/camera/ios`) - - Firebase/MLVisionBarcodeModel - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - - firebase_ml_vision (from `.symlinks/plugins/firebase_ml_vision/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - Flutter (from `Flutter`) + - qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) - url_launcher (from `.symlinks/plugins/url_launcher/ios`) @@ -143,58 +114,46 @@ SPEC REPOS: - FirebaseCore - FirebaseCoreDiagnostics - FirebaseInstallations - - FirebaseMLCommon - - FirebaseMLVision - - FirebaseMLVisionBarcodeModel - - GoogleAPIClientForREST - GoogleAppMeasurement - GoogleDataTransport - - GoogleToolboxForMac - GoogleUtilities - - GTMSessionFetcher + - MTBBarcodeScanner - nanopb - PromisesObjC - - Protobuf EXTERNAL SOURCES: - camera: - :path: ".symlinks/plugins/camera/ios" firebase_analytics: :path: ".symlinks/plugins/firebase_analytics/ios" - firebase_ml_vision: - :path: ".symlinks/plugins/firebase_ml_vision/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" Flutter: :path: Flutter + qr_code_scanner: + :path: ".symlinks/plugins/qr_code_scanner/ios" shared_preferences: :path: ".symlinks/plugins/shared_preferences/ios" url_launcher: :path: ".symlinks/plugins/url_launcher/ios" SPEC CHECKSUMS: - camera: a0ca5080336f7af47b88436e5e26da3dee5568f0 - Firebase: c23a36d9e4cdf7877dfcba8dd0c58add66358999 - firebase_analytics: 9118044ffb98bee71d84733fc594f5134fe4bc1b - firebase_ml_vision: cf3db3a9b870a2424e4c1c369b2123d31177cc9f - FirebaseAnalytics: 3bb096873ee0d7fa4b6c70f5e9166b6da413cc7f - FirebaseCore: d3a978a3cfa3240bf7e4ba7d137fdf5b22b628ec - FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1 - FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2 - FirebaseMLCommon: f42d067ca7fed962e09f02ba94a24e06ee50d933 - FirebaseMLVision: fd7cdd33d067c976c16fd521e7e92c26c980c947 - FirebaseMLVisionBarcodeModel: 394cd61c52dc03558088caf82b0dade8028f57d5 + Firebase: c121feb35e4126c0b355e3313fa9b487d47319fd + firebase_analytics: 2d95c809fde5c606276a51b9cdc591a7ba44e1f2 + firebase_core: 54856a8a39b8f3e35f34fdd3373f3b92a1daa68b + FirebaseAnalytics: cd3bd84d722a24a8923918af8af8e5236f615d77 + FirebaseCore: 907447d8917a4d3eb0cce2829c5a0ad21d90b432 + FirebaseCoreDiagnostics: 68ad972f99206cef818230f3f3179d52ccfb7f8c + FirebaseInstallations: a58d4f72ec5861840b84df489f2668d970df558a Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c - GoogleAPIClientForREST: 4bb409633efcc2e1b3f945afe7e35039b5a61db2 - GoogleAppMeasurement: a6a3a066369828db64eda428cb2856dc1cdc7c4e - GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833 - GoogleToolboxForMac: 471e0c05d39506e50e6398f46fa9a12ae0efeff9 - GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 - GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52 - nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc + GoogleAppMeasurement: fd19169c3034975cb934e865e5667bfdce59df7f + GoogleDataTransport: cd9db2180fcecd8da1b561aea31e3e56cf834aa7 + GoogleUtilities: f8a43108b38a68eebe8b3540e1f4f2d28843ce20 + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97 - Protobuf: 0cde852566359049847168e51bd1c690e0f70056 + qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef -PODFILE CHECKSUM: 92de5e6e176219356a0144477ff81b3a723353c3 +PODFILE CHECKSUM: a8ca2c5442046448bb1a68ff0be634bbd42c56b9 COCOAPODS: 1.10.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 0f7df6b..266d0c3 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -8,13 +8,13 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2DA29C0FBB34416D8BE2BCDE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24C46B04F60F051E89242449 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 86167AD425EA31100037663E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 86167AD325EA31100037663E /* GoogleService-Info.plist */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 9BAA5DBB20500894385CF0A5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FAAF4D129E5C2EDF5F8212C /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -31,11 +31,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 060D28A4F4F8769A0BAF9C07 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 1FAAF4D129E5C2EDF5F8212C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 24C46B04F60F051E89242449 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 510721ACE32D03A6A5929057 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 4C68481624A19615E0005A3D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -47,8 +48,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 99937DF4BCD0C7F6F0D565AB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 9FB3B8DD222738FCA558FFA7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + BF1FF470551191C83551EB77 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -56,7 +56,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9BAA5DBB20500894385CF0A5 /* Pods_Runner.framework in Frameworks */, + 2DA29C0FBB34416D8BE2BCDE /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -66,21 +66,13 @@ 70E9A5A024B87B4198B4019C /* Pods */ = { isa = PBXGroup; children = ( - 99937DF4BCD0C7F6F0D565AB /* Pods-Runner.debug.xcconfig */, - 9FB3B8DD222738FCA558FFA7 /* Pods-Runner.release.xcconfig */, - 510721ACE32D03A6A5929057 /* Pods-Runner.profile.xcconfig */, + BF1FF470551191C83551EB77 /* Pods-Runner.debug.xcconfig */, + 060D28A4F4F8769A0BAF9C07 /* Pods-Runner.release.xcconfig */, + 4C68481624A19615E0005A3D /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - 8CE7167CD20307CE538F10B2 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1FAAF4D129E5C2EDF5F8212C /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -100,7 +92,7 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 70E9A5A024B87B4198B4019C /* Pods */, - 8CE7167CD20307CE538F10B2 /* Frameworks */, + E1127E22EE672CF7DA100A32 /* Frameworks */, ); sourceTree = ""; }; @@ -127,6 +119,14 @@ path = Runner; sourceTree = ""; }; + E1127E22EE672CF7DA100A32 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 24C46B04F60F051E89242449 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -134,14 +134,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 608A2D97B020F5563304AF62 /* [CP] Check Pods Manifest.lock */, + D871EF31DE215F0D12B2CCA8 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 07F9E74C4210256EAF0CA9DA /* [CP] Embed Pods Frameworks */, + 27A1211FC187681962F8B7EF /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -201,7 +201,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 07F9E74C4210256EAF0CA9DA /* [CP] Embed Pods Frameworks */ = { + 27A1211FC187681962F8B7EF /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -232,41 +232,41 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 608A2D97B020F5563304AF62 /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + D871EF31DE215F0D12B2CCA8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/lib/app_config.dart b/lib/app_config.dart index 0f54054..6dbc029 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -1,17 +1,17 @@ class AppConfig { AppConfig() { params['dev'] = AppConfigParams( - "http://192.168.40.197:8545", - "ws://192.168.40.197:8545", - "0xD933a953f4786Eed5E58D234dFeadE15c96bAa8b"); + 'http://192.168.40.197:8545', + 'ws://192.168.40.197:8545', + '0xD933a953f4786Eed5E58D234dFeadE15c96bAa8b'); params['ropsten'] = AppConfigParams( - "https://ropsten.infura.io/v3/628074215a2449eb960b4fe9e95feb09", - "wss://ropsten.infura.io/ws/v3/628074215a2449eb960b4fe9e95feb09", - "0x5060b60cb8Bd1C94B7ADEF4134555CDa7B45c461"); + 'https://ropsten.infura.io/v3/628074215a2449eb960b4fe9e95feb09', + 'wss://ropsten.infura.io/ws/v3/628074215a2449eb960b4fe9e95feb09', + '0x5060b60cb8Bd1C94B7ADEF4134555CDa7B45c461'); } - Map params = Map(); + Map params = {}; } class AppConfigParams { diff --git a/lib/components/copyButton/copy_button.dart b/lib/components/copyButton/copy_button.dart index 3e5ef6f..67296e4 100644 --- a/lib/components/copyButton/copy_button.dart +++ b/lib/components/copyButton/copy_button.dart @@ -2,19 +2,24 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class CopyButton extends StatelessWidget { - CopyButton({this.text, this.value}); + const CopyButton({ + Key? key, + required this.text, + required this.value, + }) : super(key: key); + final Text text; - final String value; + final String? value; @override Widget build(BuildContext context) { return OutlinedButton( - child: this.text, + child: text, onPressed: () { - Clipboard.setData(ClipboardData(text: this.value)); + Clipboard.setData(ClipboardData(text: value)); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text("Copied"), + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Copied'), )); }, ); diff --git a/lib/components/dialog/alert.dart b/lib/components/dialog/alert.dart index e5e5667..5d48799 100644 --- a/lib/components/dialog/alert.dart +++ b/lib/components/dialog/alert.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; class Alert { - Alert({@required this.title, @required this.text, this.actions}); + Alert({required this.title, required this.text, this.actions}); final String title; final String text; - final List actions; + final List? actions; - show(BuildContext context) { - AlertDialog alert = AlertDialog( + void show(BuildContext context) { + final alert = AlertDialog( title: Text(title), content: Text(text), actions: actions, @@ -16,9 +16,7 @@ class Alert { showDialog( context: context, - builder: (BuildContext context) { - return alert; - }, + builder: (BuildContext context) => alert, ); } } diff --git a/lib/components/form/paper_form.dart b/lib/components/form/paper_form.dart index 1b609b1..752e995 100644 --- a/lib/components/form/paper_form.dart +++ b/lib/components/form/paper_form.dart @@ -1,19 +1,21 @@ import 'package:flutter/cupertino.dart'; class PaperForm extends StatelessWidget { - PaperForm({this.children, this.padding = 8, this.actionButtons}); + const PaperForm( + {Key? key, required this.children, this.padding = 8, this.actionButtons}) + : super(key: key); final List children; - final List actionButtons; + final List? actionButtons; final double padding; @override Widget build(BuildContext context) { return Form( child: Padding( - padding: EdgeInsets.all(this.padding), + padding: EdgeInsets.all(padding), child: Column(children: [ - ...this.children, + ...children, ..._buildButtons(), ]), ), @@ -21,13 +23,15 @@ class PaperForm extends StatelessWidget { } List _buildButtons() { - if (this.actionButtons == null) return [Container()]; + if (actionButtons == null) { + return List.empty(); + } return [ const SizedBox(height: 15), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: this.actionButtons, + children: actionButtons!, ) ]; } diff --git a/lib/components/form/paper_input.dart b/lib/components/form/paper_input.dart index 0e112c0..029e0b4 100644 --- a/lib/components/form/paper_input.dart +++ b/lib/components/form/paper_input.dart @@ -1,35 +1,36 @@ import 'package:flutter/material.dart'; class PaperInput extends StatelessWidget { - PaperInput({ - this.labelText, + const PaperInput({ + required this.labelText, this.hintText, this.errorText, this.onChanged, this.controller, this.maxLines, this.obscureText = false, - }); + Key? key, + }) : super(key: key); - final ValueChanged onChanged; - final String errorText; + final ValueChanged? onChanged; + final String? errorText; final String labelText; - final String hintText; + final String? hintText; final bool obscureText; - final int maxLines; - final TextEditingController controller; + final int? maxLines; + final TextEditingController? controller; @override Widget build(BuildContext context) { return TextField( - obscureText: this.obscureText, - controller: this.controller, - onChanged: this.onChanged, - maxLines: this.maxLines, + obscureText: obscureText, + controller: controller, + onChanged: onChanged, + maxLines: maxLines, decoration: InputDecoration( - labelText: this.labelText, - hintText: this.hintText, - errorText: this.errorText, + labelText: labelText, + hintText: hintText, + errorText: errorText, ), ); } diff --git a/lib/components/form/paper_radio.dart b/lib/components/form/paper_radio.dart index 96bea66..e2008b1 100644 --- a/lib/components/form/paper_radio.dart +++ b/lib/components/form/paper_radio.dart @@ -6,12 +6,18 @@ typedef OnRadioChanged = void Function( ); class PaperRadio extends StatelessWidget { - PaperRadio(this.title, {this.value, this.groupValue, this.onChanged}); + const PaperRadio( + this.title, { + this.value, + this.groupValue, + this.onChanged, + Key? key, + }) : super(key: key); final dynamic value; final String title; final dynamic groupValue; - final OnRadioChanged onChanged; + final OnRadioChanged? onChanged; @override Widget build(BuildContext context) { return Row( diff --git a/lib/components/form/paper_validation_summary.dart b/lib/components/form/paper_validation_summary.dart index d6680d8..06046d0 100644 --- a/lib/components/form/paper_validation_summary.dart +++ b/lib/components/form/paper_validation_summary.dart @@ -1,12 +1,12 @@ import 'package:flutter/cupertino.dart'; class PaperValidationSummary extends StatelessWidget { - PaperValidationSummary(this.errors); + const PaperValidationSummary(this.errors, {Key? key}) : super(key: key); final List errors; @override Widget build(BuildContext context) { return Column( - children: this.errors.map((error) => Text(error)).toList(), + children: errors.map((error) => Text(error)).toList(), ); } } diff --git a/lib/components/menu/main_menu.dart b/lib/components/menu/main_menu.dart index 8eff1da..4924301 100644 --- a/lib/components/menu/main_menu.dart +++ b/lib/components/menu/main_menu.dart @@ -3,10 +3,16 @@ import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; class MainMenu extends StatelessWidget { - MainMenu({this.address, this.onReset}); + const MainMenu({ + Key? key, + required this.address, + required this.onReset, + required this.onRevealKey, + }) : super(key: key); - final String address; - final Function onReset; + final String? address; + final GestureTapCallback? onReset; + final GestureTapCallback? onRevealKey; @override Widget build(BuildContext context) { @@ -14,11 +20,11 @@ class MainMenu extends StatelessWidget { child: ListView( children: [ ListTile( - title: Text("Get tokens"), - subtitle: Text("Claim some test tokens"), - trailing: Icon(WalletIcons.gem, color: Colors.blue), + title: const Text('Get tokens'), + subtitle: const Text('Claim some test tokens'), + trailing: const Icon(WalletIcons.gem, color: Colors.blue), onTap: () async { - var url = 'https://faucet.clempe.dev?address=${this.address}'; + var url = 'https://faucet.clempe.dev?address=$address'; if (await canLaunch(url)) { await launch(url); } else { @@ -27,14 +33,14 @@ class MainMenu extends StatelessWidget { }, ), ListTile( - title: Text("Get ETH"), - subtitle: Text("Claim some test ether"), - trailing: Icon( + title: const Text('Get ETH'), + subtitle: const Text('Claim some test ether'), + trailing: const Icon( WalletIcons.ethereum, color: Colors.black, ), onTap: () async { - var url = 'https://faucet.ropsten.be'; + const url = 'https://faucet.ropsten.be'; if (await canLaunch(url)) { await launch(url); } else { @@ -43,13 +49,21 @@ class MainMenu extends StatelessWidget { }, ), ListTile( - title: Text("Reset wallet"), - subtitle: Text("Wipe all wallet data"), - trailing: Icon( + title: const Text('Private key'), + subtitle: const Text('Reveal your private key'), + trailing: const Icon( + WalletIcons.key, + color: Colors.black, + ), + onTap: onRevealKey), + ListTile( + title: const Text('Reset wallet'), + subtitle: const Text('Wipe all wallet data'), + trailing: const Icon( WalletIcons.skull, color: Colors.orange, ), - onTap: this.onReset), + onTap: onReset), ], ), ); diff --git a/lib/components/wallet/balance.dart b/lib/components/wallet/balance.dart index e5755ce..c31ebd8 100644 --- a/lib/components/wallet/balance.dart +++ b/lib/components/wallet/balance.dart @@ -4,11 +4,16 @@ import 'package:flutter/material.dart'; import 'package:qr_flutter/qr_flutter.dart'; class Balance extends StatelessWidget { - Balance({this.address, this.ethBalance, this.tokenBalance}); + const Balance({ + Key? key, + required this.address, + required this.ethBalance, + required this.tokenBalance, + }) : super(key: key); - final String address; - final BigInt ethBalance; - final BigInt tokenBalance; + final String? address; + final BigInt? ethBalance; + final BigInt? tokenBalance; @override Widget build(BuildContext context) { @@ -16,26 +21,27 @@ class Balance extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(address ?? ""), + Text(address ?? ''), CopyButton( text: const Text('Copy address'), value: address, ), - QrImage( - data: address ?? "", - size: 150.0, - ), + if (address != null) + QrImage( + data: address!, + size: 150.0, + ), Text( - "${EthAmountFormatter(tokenBalance).format()} tokens", + '${EthAmountFormatter(tokenBalance).format()} tokens', style: - Theme.of(context).textTheme.bodyText2.apply(fontSizeDelta: 6), + Theme.of(context).textTheme.bodyText2?.apply(fontSizeDelta: 6), ), Text( - "${EthAmountFormatter(ethBalance).format()} eth", + '${EthAmountFormatter(ethBalance).format()} eth', style: Theme.of(context) .textTheme .bodyText2 - .apply(color: Colors.blueGrey), + ?.apply(color: Colors.blueGrey), ) ], ), diff --git a/lib/components/wallet/confirm_mnemonic.dart b/lib/components/wallet/confirm_mnemonic.dart index a6a5c47..05208fa 100644 --- a/lib/components/wallet/confirm_mnemonic.dart +++ b/lib/components/wallet/confirm_mnemonic.dart @@ -6,37 +6,37 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class ConfirmMnemonic extends HookWidget { - ConfirmMnemonic( - {this.mnemonic, this.errors, this.onConfirm, this.onGenerateNew}); + const ConfirmMnemonic( + {Key? key, this.errors, this.onConfirm, this.onGenerateNew}) + : super(key: key); - final String mnemonic; - final List errors; - final Function onConfirm; - final Function onGenerateNew; + final List? errors; + final Function(String)? onConfirm; + final VoidCallback? onGenerateNew; @override Widget build(BuildContext context) { - var mnemonicController = useTextEditingController(); + final mnemonicController = useTextEditingController(); return Center( child: Container( - margin: EdgeInsets.all(25), + margin: const EdgeInsets.all(25), child: SingleChildScrollView( child: PaperForm( padding: 30, actionButtons: [ OutlinedButton( child: const Text('Generate New'), - onPressed: this.onGenerateNew, + onPressed: onGenerateNew, ), ElevatedButton( child: const Text('Confirm'), - onPressed: this.onConfirm != null - ? () => this.onConfirm(mnemonicController.value.text) + onPressed: onConfirm != null + ? () => onConfirm!(mnemonicController.value.text) : null, ) ], children: [ - PaperValidationSummary(this.errors), + if (errors != null) PaperValidationSummary(errors!), PaperInput( labelText: 'Confirm your seed', hintText: 'Please type your seed phrase again', diff --git a/lib/components/wallet/display_mnemonic.dart b/lib/components/wallet/display_mnemonic.dart index b81d01b..5e19fee 100644 --- a/lib/components/wallet/display_mnemonic.dart +++ b/lib/components/wallet/display_mnemonic.dart @@ -4,43 +4,35 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class DisplayMnemonic extends HookWidget { - DisplayMnemonic({this.mnemonic, this.onNext}); + const DisplayMnemonic({Key? key, required this.mnemonic, this.onNext}) + : super(key: key); final String mnemonic; - final Function onNext; + final VoidCallback? onNext; @override Widget build(BuildContext context) { return Center( child: Container( - margin: EdgeInsets.all(25), + margin: const EdgeInsets.all(25), child: SingleChildScrollView( child: Column( children: [ - Text( - "Get a piece of papper, write down your seed phrase and keep it safe. This is the only way to recover your funds.", + const Text( + 'Get a piece of papper, write down your seed phrase and keep it safe. This is the only way to recover your funds.', textAlign: TextAlign.center, ), Container( - margin: EdgeInsets.all(25), - padding: EdgeInsets.all(10), + margin: const EdgeInsets.all(25), + padding: const EdgeInsets.all(10), decoration: BoxDecoration(border: Border.all()), - child: Text( - this.mnemonic, - textAlign: TextAlign.center, - ), + child: Text(mnemonic, textAlign: TextAlign.center), ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - CopyButton( - text: const Text('Copy'), - value: this.mnemonic, - ), - ElevatedButton( - child: const Text('Next'), - onPressed: this.onNext, - ) + CopyButton(text: const Text('Copy'), value: mnemonic), + ElevatedButton(child: const Text('Next'), onPressed: onNext) ], ) ], diff --git a/lib/components/wallet/import_wallet_form.dart b/lib/components/wallet/import_wallet_form.dart index ab9374c..24f532b 100644 --- a/lib/components/wallet/import_wallet_form.dart +++ b/lib/components/wallet/import_wallet_form.dart @@ -7,28 +7,29 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class ImportWalletForm extends HookWidget { - ImportWalletForm({this.onImport, this.errors}); + const ImportWalletForm({Key? key, this.onImport, this.errors}) + : super(key: key); - final Function(WalletImportType type, String value) onImport; - final List errors; + final Function(WalletImportType type, String value)? onImport; + final List? errors; @override Widget build(BuildContext context) { - var importType = useState(WalletImportType.mnemonic); - var inputController = useTextEditingController(); + final importType = useState(WalletImportType.mnemonic); + final inputController = useTextEditingController(); return Center( child: Container( - margin: EdgeInsets.all(25), + margin: const EdgeInsets.all(25), child: SingleChildScrollView( child: PaperForm( padding: 30, actionButtons: [ ElevatedButton( child: const Text('Import'), - onPressed: this.onImport != null - ? () => this - .onImport(importType.value, inputController.value.text) + onPressed: onImport != null + ? () => + onImport!(importType.value, inputController.value.text) : null, ) ], @@ -36,16 +37,18 @@ class ImportWalletForm extends HookWidget { Row( children: [ PaperRadio( - "Seed", + 'Seed', groupValue: importType.value, value: WalletImportType.mnemonic, - onChanged: (value) => importType.value = value, + onChanged: (value) => + importType.value = value as WalletImportType, ), PaperRadio( - "Private Key", + 'Private Key', groupValue: importType.value, value: WalletImportType.privateKey, - onChanged: (value) => importType.value = value, + onChanged: (value) => + importType.value = value as WalletImportType, ), ], ), @@ -73,13 +76,13 @@ class ImportWalletForm extends HookWidget { } Widget fieldForm({ - String label, - String hintText, - TextEditingController controller, + required String label, + required String hintText, + required TextEditingController controller, }) { return Column( children: [ - PaperValidationSummary(errors), + if (errors != null) PaperValidationSummary(errors!), PaperInput( labelText: label, hintText: hintText, diff --git a/lib/components/wallet/loading.dart b/lib/components/wallet/loading.dart index fee30b6..e6de6cb 100644 --- a/lib/components/wallet/loading.dart +++ b/lib/components/wallet/loading.dart @@ -2,18 +2,21 @@ import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; class Loading extends StatelessWidget { + const Loading({Key? key}) : super(key: key); + + @override Widget build(BuildContext context) { return Center( child: Container( - padding: EdgeInsets.all(25), + padding: const EdgeInsets.all(25), child: Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: const [ Text( 'Your transaction is being processed', textAlign: TextAlign.center, ), - const SizedBox(height: 48.0), + SizedBox(height: 48.0), SpinKitWanderingCubes(color: Colors.blue), ], ), diff --git a/lib/components/wallet/transfer_form.dart b/lib/components/wallet/transfer_form.dart index 0580832..1032de7 100644 --- a/lib/components/wallet/transfer_form.dart +++ b/lib/components/wallet/transfer_form.dart @@ -6,12 +6,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class TransferForm extends HookWidget { - TransferForm({ - this.address, - @required this.onSubmit, - }); + const TransferForm({ + Key? key, + required this.address, + required this.onSubmit, + }) : super(key: key); - final String address; + final String? address; final void Function(String address, String amount) onSubmit; @override @@ -21,29 +22,28 @@ class TransferForm extends HookWidget { final transferStore = useWalletTransfer(context); useEffect(() { - if (address != null) toController.value = TextEditingValue(text: address); - return null; + if (address != null) + toController.value = TextEditingValue(text: address!); }, [address]); return Center( child: Container( - margin: EdgeInsets.all(25), + margin: const EdgeInsets.all(25), child: SingleChildScrollView( child: PaperForm( padding: 30, actionButtons: [ ElevatedButton( child: const Text('Transfer now'), - onPressed: () { - this.onSubmit( - toController.value.text, - amountController.value.text, - ); - }, + onPressed: () => onSubmit( + toController.value.text, + amountController.value.text, + ), ) ], children: [ - PaperValidationSummary(transferStore.state.errors.toList()), + if (transferStore.state.errors != null) + PaperValidationSummary(transferStore.state.errors!.toList()), PaperInput( controller: toController, labelText: 'To', diff --git a/lib/context/hook_provider.dart b/lib/context/hook_provider.dart index 8e32312..7e426d3 100644 --- a/lib/context/hook_provider.dart +++ b/lib/context/hook_provider.dart @@ -6,17 +6,18 @@ typedef HookWidgetBuilder = Widget Function( BuildContext context, Handler store); abstract class ContextProviderWidget extends HookWidget { - final Widget child; - final HookWidgetBuilder builder; + const ContextProviderWidget({this.child, this.builder, Key? key}) + : super(key: key); - ContextProviderWidget({this.child, this.builder}); + final Widget? child; + final HookWidgetBuilder? builder; Widget provide(BuildContext context, T handler) { return MultiProvider( providers: [ Provider.value(value: handler), ], - child: builder != null ? builder(context, handler) : child, + child: builder != null ? builder!(context, handler) : child, ); } } diff --git a/lib/context/setup/wallet_setup_handler.dart b/lib/context/setup/wallet_setup_handler.dart index 1c37f42..8f097be 100644 --- a/lib/context/setup/wallet_setup_handler.dart +++ b/lib/context/setup/wallet_setup_handler.dart @@ -15,14 +15,14 @@ class WalletSetupHandler { WalletSetup get state => _store.state; void generateMnemonic() { - var mnemonic = _addressService.generateMnemonic(); + final mnemonic = _addressService.generateMnemonic(); _store.dispatch(WalletSetupConfirmMnemonic(mnemonic)); } Future confirmMnemonic(String mnemonic) async { if (state.mnemonic != mnemonic) { _store - .dispatch(WalletSetupAddError("Invalid mnemonic, please try again.")); + .dispatch(WalletSetupAddError('Invalid mnemonic, please try again.')); return false; } _store.dispatch(WalletSetupStarted()); @@ -50,7 +50,7 @@ class WalletSetupHandler { } _store.dispatch( - WalletSetupAddError("Invalid mnemonic, it requires 12 words.")); + WalletSetupAddError('Invalid mnemonic, it requires 12 words.')); return false; } @@ -66,18 +66,18 @@ class WalletSetupHandler { } _store.dispatch( - WalletSetupAddError("Invalid private key, please try again.")); + WalletSetupAddError('Invalid private key, please try again.')); return false; } String _mnemonicNormalise(String mnemonic) { - return _mnemonicWords(mnemonic).join(" "); + return _mnemonicWords(mnemonic).join(' '); } List _mnemonicWords(String mnemonic) { return mnemonic - .split(" ") + .split(' ') .where((item) => item != null && item.trim().isNotEmpty) .map((item) => item.trim()) .toList(); diff --git a/lib/context/setup/wallet_setup_provider.dart b/lib/context/setup/wallet_setup_provider.dart index 3cad380..ba293c2 100644 --- a/lib/context/setup/wallet_setup_provider.dart +++ b/lib/context/setup/wallet_setup_provider.dart @@ -10,14 +10,14 @@ import 'package:provider/provider.dart'; import '../hook_provider.dart'; class WalletSetupProvider extends ContextProviderWidget { - WalletSetupProvider( - {Widget child, HookWidgetBuilder builder}) - : super(child: child, builder: builder); + const WalletSetupProvider( + {Widget? child, HookWidgetBuilder? builder, Key? key}) + : super(child: child, builder: builder, key: key); @override Widget build(BuildContext context) { final store = useReducer(reducer, - initialState: WalletSetup()); + initialState: WalletSetup(), initialAction: WalletSetupInit()); final addressService = Provider.of(context); final handler = useMemoized( @@ -29,8 +29,5 @@ class WalletSetupProvider extends ContextProviderWidget { } } -WalletSetupHandler useWalletSetup(BuildContext context) { - var handler = Provider.of(context); - - return handler; -} +WalletSetupHandler useWalletSetup(BuildContext context) => + Provider.of(context); diff --git a/lib/context/setup/wallet_setup_state.dart b/lib/context/setup/wallet_setup_state.dart index bb52235..0ad7fc0 100644 --- a/lib/context/setup/wallet_setup_state.dart +++ b/lib/context/setup/wallet_setup_state.dart @@ -2,6 +2,8 @@ import 'package:etherwallet/model/wallet_setup.dart'; abstract class WalletSetupAction {} +class WalletSetupInit implements WalletSetupAction {} + class WalletSetupConfirmMnemonic implements WalletSetupAction { WalletSetupConfirmMnemonic(this.mnemonic); final String mnemonic; @@ -25,6 +27,10 @@ class WalletSetupChangeMethod implements WalletSetupAction { class WalletSetupStarted implements WalletSetupAction {} WalletSetup reducer(WalletSetup state, WalletSetupAction action) { + if (action is WalletSetupInit) { + return WalletSetup(); + } + if (action is WalletSetupConfirmMnemonic) { return state.rebuild((b) => b ..mnemonic = action.mnemonic diff --git a/lib/context/transfer/wallet_transfer_handler.dart b/lib/context/transfer/wallet_transfer_handler.dart index 2c8a5c6..7c46947 100644 --- a/lib/context/transfer/wallet_transfer_handler.dart +++ b/lib/context/transfer/wallet_transfer_handler.dart @@ -22,14 +22,14 @@ class WalletTransferHandler { WalletTransfer get state => _store.state; Future transfer(String to, String amount) async { - var completer = new Completer(); - var privateKey = _configurationService.getPrivateKey(); + final completer = Completer(); + final privateKey = _configurationService.getPrivateKey(); _store.dispatch(WalletTransferStarted()); try { await _contractService.send( - privateKey, + privateKey!, EthereumAddress.fromHex(to), BigInt.from(double.parse(amount) * pow(10, 18)), onTransfer: (from, to, value) { diff --git a/lib/context/transfer/wallet_transfer_provider.dart b/lib/context/transfer/wallet_transfer_provider.dart index 06c0660..4c4f877 100644 --- a/lib/context/transfer/wallet_transfer_provider.dart +++ b/lib/context/transfer/wallet_transfer_provider.dart @@ -12,14 +12,16 @@ import '../hook_provider.dart'; class WalletTransferProvider extends ContextProviderWidget { - WalletTransferProvider( - {Widget child, HookWidgetBuilder builder}) - : super(child: child, builder: builder); + const WalletTransferProvider( + {Widget? child, + HookWidgetBuilder? builder, + Key? key}) + : super(child: child, builder: builder, key: key); @override Widget build(BuildContext context) { final store = useReducer(reducer, - initialState: WalletTransfer()); + initialState: WalletTransfer(), initialAction: WalletTransferInit()); final contractService = Provider.of(context); final configurationService = Provider.of(context); @@ -32,8 +34,5 @@ class WalletTransferProvider } } -WalletTransferHandler useWalletTransfer(BuildContext context) { - var handler = Provider.of(context); - - return handler; -} +WalletTransferHandler useWalletTransfer(BuildContext context) => + Provider.of(context); diff --git a/lib/context/transfer/wallet_transfer_state.dart b/lib/context/transfer/wallet_transfer_state.dart index 0d26c25..fc7b2db 100644 --- a/lib/context/transfer/wallet_transfer_state.dart +++ b/lib/context/transfer/wallet_transfer_state.dart @@ -2,6 +2,8 @@ import 'package:etherwallet/model/wallet_transfer.dart'; abstract class WalletTransferAction {} +class WalletTransferInit implements WalletTransferAction {} + class WalletTransferStarted implements WalletTransferAction {} class WalletTransferError implements WalletTransferAction { @@ -12,6 +14,10 @@ class WalletTransferError implements WalletTransferAction { class WalletTransferConfirmed implements WalletTransferAction {} WalletTransfer reducer(WalletTransfer state, WalletTransferAction action) { + if (action is WalletTransferInit) { + return WalletTransfer(); + } + if (action is WalletTransferStarted) { return state.rebuild((b) => b ..errors.clear() diff --git a/lib/context/wallet/wallet_handler.dart b/lib/context/wallet/wallet_handler.dart index 84db736..654c34c 100644 --- a/lib/context/wallet/wallet_handler.dart +++ b/lib/context/wallet/wallet_handler.dart @@ -30,13 +30,17 @@ class WalletHandler { _initialiseFromMnemonic(entropyMnemonic); return; } + if (privateKey != null && privateKey.isNotEmpty) { + _initialiseFromPrivateKey(privateKey); + return; + } - _initialiseFromPrivateKey(privateKey); + throw Exception('Wallet could not be initialised.'); } Future _initialiseFromMnemonic(String entropyMnemonic) async { final mnemonic = _addressService.entropyToMnemonic(entropyMnemonic); - final privateKey = _addressService.getPrivateKey(mnemonic); + final privateKey = await _addressService.getPrivateKey(mnemonic); final address = await _addressService.getPublicAddress(privateKey); _store.dispatch(InitialiseWallet(address.toString(), privateKey)); @@ -53,11 +57,11 @@ class WalletHandler { } Future _initialise() async { - await this.fetchOwnBalance(); + await fetchOwnBalance(); _contractService.listenTransfer((from, to, value) async { - var fromMe = from.toString() == state.address; - var toMe = to.toString() == state.address; + final fromMe = from.toString() == state.address; + final toMe = to.toString() == state.address; if (!fromMe && !toMe) { return; @@ -70,13 +74,17 @@ class WalletHandler { } Future fetchOwnBalance() async { + if (state.address?.isEmpty ?? true) { + return; + } + _store.dispatch(UpdatingBalance()); - var tokenBalance = await _contractService - .getTokenBalance(web3.EthereumAddress.fromHex(state.address)); + final tokenBalance = await _contractService + .getTokenBalance(web3.EthereumAddress.fromHex(state.address!)); - var ethBalance = await _contractService - .getEthBalance(web3.EthereumAddress.fromHex(state.address)); + final ethBalance = await _contractService + .getEthBalance(web3.EthereumAddress.fromHex(state.address!)); _store.dispatch(BalanceUpdated(ethBalance.getInWei, tokenBalance)); } @@ -85,4 +93,8 @@ class WalletHandler { await _configurationService.setMnemonic(null); await _configurationService.setupDone(false); } + + String? getPrivateKey() { + return _configurationService.getPrivateKey(); + } } diff --git a/lib/context/wallet/wallet_provider.dart b/lib/context/wallet/wallet_provider.dart index 05e5d0c..279bf42 100644 --- a/lib/context/wallet/wallet_provider.dart +++ b/lib/context/wallet/wallet_provider.dart @@ -4,21 +4,24 @@ import 'package:etherwallet/service/configuration_service.dart'; import 'package:etherwallet/service/contract_service.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; - import 'package:provider/provider.dart'; import '../hook_provider.dart'; -import 'wallet_state.dart'; import 'wallet_handler.dart'; +import 'wallet_state.dart'; class WalletProvider extends ContextProviderWidget { - WalletProvider({Widget child, HookWidgetBuilder builder}) - : super(child: child, builder: builder); + const WalletProvider( + {Key? key, Widget? child, HookWidgetBuilder? builder}) + : super(child: child, builder: builder, key: key); @override Widget build(BuildContext context) { - final store = - useReducer(reducer, initialState: Wallet()); + final store = useReducer( + reducer, + initialState: Wallet(), + initialAction: WalletInit(), + ); final addressService = Provider.of(context); final contractService = Provider.of(context); @@ -37,8 +40,5 @@ class WalletProvider extends ContextProviderWidget { } } -WalletHandler useWallet(BuildContext context) { - var handler = Provider.of(context); - - return handler; -} +WalletHandler useWallet(BuildContext context) => + Provider.of(context); diff --git a/lib/context/wallet/wallet_state.dart b/lib/context/wallet/wallet_state.dart index 7966b7f..4c58523 100644 --- a/lib/context/wallet/wallet_state.dart +++ b/lib/context/wallet/wallet_state.dart @@ -2,6 +2,8 @@ import 'package:etherwallet/model/wallet.dart'; abstract class WalletAction {} +class WalletInit extends WalletAction {} + class InitialiseWallet extends WalletAction { InitialiseWallet(this.address, this.privateKey); final String address; @@ -17,6 +19,10 @@ class BalanceUpdated extends WalletAction { class UpdatingBalance extends WalletAction {} Wallet reducer(Wallet state, WalletAction action) { + if (action is WalletInit) { + return Wallet(); + } + if (action is InitialiseWallet) { return state.rebuild((b) => b ..address = action.address diff --git a/lib/intro_page.dart b/lib/intro_page.dart index 16ee146..1b72e0f 100644 --- a/lib/intro_page.dart +++ b/lib/intro_page.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; class IntroPage extends StatelessWidget { + const IntroPage({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( @@ -10,17 +12,17 @@ class IntroPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ ElevatedButton( - child: Text("Create new wallet"), + child: const Text('Create new wallet'), onPressed: () { - Navigator.of(context).pushNamed("/create"); + Navigator.of(context).pushNamed('/create'); }, ), Container( - padding: EdgeInsets.all(10), + padding: const EdgeInsets.all(10), child: OutlinedButton( - child: Text("Import wallet"), + child: const Text('Import wallet'), onPressed: () { - Navigator.of(context).pushNamed("/import"); + Navigator.of(context).pushNamed('/import'); }, ), ) diff --git a/lib/main.dart b/lib/main.dart index 485719a..184c4d8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,16 +7,16 @@ import 'package:provider/provider.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:provider/single_child_widget.dart'; -void main() async { +Future main() async { // bootstrapping; WidgetsFlutterBinding.ensureInitialized(); - final stores = await createProviders(AppConfig().params["ropsten"]); + final stores = await createProviders(AppConfig().params['ropsten']!); runApp(MainApp(stores)); } class MainApp extends StatelessWidget { - MainApp(this.stores); + MainApp(this.stores, {Key? key}) : super(key: key); final List stores; final FirebaseAnalytics analytics = FirebaseAnalytics(); @@ -25,7 +25,7 @@ class MainApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: stores, - child: new MaterialApp( + child: MaterialApp( title: 'Flutter App', initialRoute: '/', routes: getRoutes(context), @@ -43,7 +43,7 @@ class MainApp extends StatelessWidget { // Notice that the counter didn't reset back to zero; the application // is not restarted. primarySwatch: Colors.blue, - buttonTheme: ButtonThemeData( + buttonTheme: const ButtonThemeData( buttonColor: Colors.blue, textTheme: ButtonTextTheme.primary, ), diff --git a/lib/model/wallet.dart b/lib/model/wallet.dart index ba56ad3..62ea1fc 100644 --- a/lib/model/wallet.dart +++ b/lib/model/wallet.dart @@ -4,11 +4,18 @@ import 'package:built_value/built_value.dart'; part 'wallet.g.dart'; abstract class Wallet implements Built { - @nullable - String get address; + factory Wallet([void Function(WalletBuilder)? updates]) => _$Wallet((b) => b + ..tokenBalance = BigInt.from(0) + ..ethBalance = BigInt.from(0) + ..errors = BuiltList().toBuilder() + ..loading = false + ..update(updates)); + + Wallet._(); + + String? get address; - @nullable - String get privateKey; + String? get privateKey; BigInt get tokenBalance; @@ -16,14 +23,5 @@ abstract class Wallet implements Built { bool get loading; - @nullable - BuiltList get errors; - - Wallet._(); - factory Wallet([void Function(WalletBuilder) updates]) => _$Wallet((b) => b - ..tokenBalance = BigInt.from(0) - ..ethBalance = BigInt.from(0) - ..errors = BuiltList().toBuilder() - ..loading = false - ..update(updates)); + BuiltList? get errors; } diff --git a/lib/model/wallet.g.dart b/lib/model/wallet.g.dart index 398c4ae..2487ee9 100644 --- a/lib/model/wallet.g.dart +++ b/lib/model/wallet.g.dart @@ -8,9 +8,9 @@ part of 'wallet.dart'; class _$Wallet extends Wallet { @override - final String address; + final String? address; @override - final String privateKey; + final String? privateKey; @override final BigInt tokenBalance; @override @@ -18,17 +18,17 @@ class _$Wallet extends Wallet { @override final bool loading; @override - final BuiltList errors; + final BuiltList? errors; - factory _$Wallet([void Function(WalletBuilder) updates]) => + factory _$Wallet([void Function(WalletBuilder)? updates]) => (new WalletBuilder()..update(updates)).build(); _$Wallet._( {this.address, this.privateKey, - this.tokenBalance, - this.ethBalance, - this.loading, + required this.tokenBalance, + required this.ethBalance, + required this.loading, this.errors}) : super._() { BuiltValueNullFieldError.checkNotNull( @@ -82,32 +82,32 @@ class _$Wallet extends Wallet { } class WalletBuilder implements Builder { - _$Wallet _$v; + _$Wallet? _$v; - String _address; - String get address => _$this._address; - set address(String address) => _$this._address = address; + String? _address; + String? get address => _$this._address; + set address(String? address) => _$this._address = address; - String _privateKey; - String get privateKey => _$this._privateKey; - set privateKey(String privateKey) => _$this._privateKey = privateKey; + String? _privateKey; + String? get privateKey => _$this._privateKey; + set privateKey(String? privateKey) => _$this._privateKey = privateKey; - BigInt _tokenBalance; - BigInt get tokenBalance => _$this._tokenBalance; - set tokenBalance(BigInt tokenBalance) => _$this._tokenBalance = tokenBalance; + BigInt? _tokenBalance; + BigInt? get tokenBalance => _$this._tokenBalance; + set tokenBalance(BigInt? tokenBalance) => _$this._tokenBalance = tokenBalance; - BigInt _ethBalance; - BigInt get ethBalance => _$this._ethBalance; - set ethBalance(BigInt ethBalance) => _$this._ethBalance = ethBalance; + BigInt? _ethBalance; + BigInt? get ethBalance => _$this._ethBalance; + set ethBalance(BigInt? ethBalance) => _$this._ethBalance = ethBalance; - bool _loading; - bool get loading => _$this._loading; - set loading(bool loading) => _$this._loading = loading; + bool? _loading; + bool? get loading => _$this._loading; + set loading(bool? loading) => _$this._loading = loading; - ListBuilder _errors; + ListBuilder? _errors; ListBuilder get errors => _$this._errors ??= new ListBuilder(); - set errors(ListBuilder errors) => _$this._errors = errors; + set errors(ListBuilder? errors) => _$this._errors = errors; WalletBuilder(); @@ -132,7 +132,7 @@ class WalletBuilder implements Builder { } @override - void update(void Function(WalletBuilder) updates) { + void update(void Function(WalletBuilder)? updates) { if (updates != null) updates(this); } @@ -152,7 +152,7 @@ class WalletBuilder implements Builder { loading, 'Wallet', 'loading'), errors: _errors?.build()); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'errors'; _errors?.build(); diff --git a/lib/model/wallet_setup.dart b/lib/model/wallet_setup.dart index 384ae49..86ad26c 100644 --- a/lib/model/wallet_setup.dart +++ b/lib/model/wallet_setup.dart @@ -10,24 +10,22 @@ enum WalletCreateSteps { display, confirm } enum WalletImportType { mnemonic, privateKey } abstract class WalletSetup implements Built { - @nullable - String get mnemonic; - - @nullable - String get privateKey; - - WalletCreateSteps get step; - WalletSetupMethod get method; - bool get loading; - @nullable - BuiltList get errors; - - WalletSetup._(); - factory WalletSetup([void Function(WalletSetupBuilder) updates]) => + factory WalletSetup([void Function(WalletSetupBuilder)? updates]) => _$WalletSetup((b) => b ..step = WalletCreateSteps.display ..method = WalletSetupMethod.create ..loading = false ..errors = BuiltList().toBuilder() ..update(updates)); + + WalletSetup._(); + + String? get mnemonic; + + String? get privateKey; + + WalletCreateSteps get step; + WalletSetupMethod get method; + bool get loading; + BuiltList? get errors; } diff --git a/lib/model/wallet_setup.g.dart b/lib/model/wallet_setup.g.dart index 3cfcb80..5a7a1c1 100644 --- a/lib/model/wallet_setup.g.dart +++ b/lib/model/wallet_setup.g.dart @@ -8,9 +8,9 @@ part of 'wallet_setup.dart'; class _$WalletSetup extends WalletSetup { @override - final String mnemonic; + final String? mnemonic; @override - final String privateKey; + final String? privateKey; @override final WalletCreateSteps step; @override @@ -18,17 +18,17 @@ class _$WalletSetup extends WalletSetup { @override final bool loading; @override - final BuiltList errors; + final BuiltList? errors; - factory _$WalletSetup([void Function(WalletSetupBuilder) updates]) => + factory _$WalletSetup([void Function(WalletSetupBuilder)? updates]) => (new WalletSetupBuilder()..update(updates)).build(); _$WalletSetup._( {this.mnemonic, this.privateKey, - this.step, - this.method, - this.loading, + required this.step, + required this.method, + required this.loading, this.errors}) : super._() { BuiltValueNullFieldError.checkNotNull(step, 'WalletSetup', 'step'); @@ -81,32 +81,32 @@ class _$WalletSetup extends WalletSetup { } class WalletSetupBuilder implements Builder { - _$WalletSetup _$v; + _$WalletSetup? _$v; - String _mnemonic; - String get mnemonic => _$this._mnemonic; - set mnemonic(String mnemonic) => _$this._mnemonic = mnemonic; + String? _mnemonic; + String? get mnemonic => _$this._mnemonic; + set mnemonic(String? mnemonic) => _$this._mnemonic = mnemonic; - String _privateKey; - String get privateKey => _$this._privateKey; - set privateKey(String privateKey) => _$this._privateKey = privateKey; + String? _privateKey; + String? get privateKey => _$this._privateKey; + set privateKey(String? privateKey) => _$this._privateKey = privateKey; - WalletCreateSteps _step; - WalletCreateSteps get step => _$this._step; - set step(WalletCreateSteps step) => _$this._step = step; + WalletCreateSteps? _step; + WalletCreateSteps? get step => _$this._step; + set step(WalletCreateSteps? step) => _$this._step = step; - WalletSetupMethod _method; - WalletSetupMethod get method => _$this._method; - set method(WalletSetupMethod method) => _$this._method = method; + WalletSetupMethod? _method; + WalletSetupMethod? get method => _$this._method; + set method(WalletSetupMethod? method) => _$this._method = method; - bool _loading; - bool get loading => _$this._loading; - set loading(bool loading) => _$this._loading = loading; + bool? _loading; + bool? get loading => _$this._loading; + set loading(bool? loading) => _$this._loading = loading; - ListBuilder _errors; + ListBuilder? _errors; ListBuilder get errors => _$this._errors ??= new ListBuilder(); - set errors(ListBuilder errors) => _$this._errors = errors; + set errors(ListBuilder? errors) => _$this._errors = errors; WalletSetupBuilder(); @@ -131,7 +131,7 @@ class WalletSetupBuilder implements Builder { } @override - void update(void Function(WalletSetupBuilder) updates) { + void update(void Function(WalletSetupBuilder)? updates) { if (updates != null) updates(this); } @@ -151,7 +151,7 @@ class WalletSetupBuilder implements Builder { loading, 'WalletSetup', 'loading'), errors: _errors?.build()); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'errors'; _errors?.build(); diff --git a/lib/model/wallet_transfer.dart b/lib/model/wallet_transfer.dart index 5362e46..7f204b8 100644 --- a/lib/model/wallet_transfer.dart +++ b/lib/model/wallet_transfer.dart @@ -7,18 +7,18 @@ enum WalletTransferStatus { started, confirmed, none } abstract class WalletTransfer implements Built { - @nullable - BuiltList get errors; - - WalletTransferStatus get status; - - bool get loading; - - WalletTransfer._(); - factory WalletTransfer([void Function(WalletTransferBuilder) updates]) => + factory WalletTransfer([void Function(WalletTransferBuilder)? updates]) => _$WalletTransfer((b) => b ..errors = BuiltList().toBuilder() ..status = WalletTransferStatus.none ..loading = false ..update(updates)); + + WalletTransfer._(); + + BuiltList? get errors; + + WalletTransferStatus get status; + + bool get loading; } diff --git a/lib/model/wallet_transfer.g.dart b/lib/model/wallet_transfer.g.dart index e285e9d..41caa66 100644 --- a/lib/model/wallet_transfer.g.dart +++ b/lib/model/wallet_transfer.g.dart @@ -8,16 +8,17 @@ part of 'wallet_transfer.dart'; class _$WalletTransfer extends WalletTransfer { @override - final BuiltList errors; + final BuiltList? errors; @override final WalletTransferStatus status; @override final bool loading; - factory _$WalletTransfer([void Function(WalletTransferBuilder) updates]) => + factory _$WalletTransfer([void Function(WalletTransferBuilder)? updates]) => (new WalletTransferBuilder()..update(updates)).build(); - _$WalletTransfer._({this.errors, this.status, this.loading}) : super._() { + _$WalletTransfer._({this.errors, required this.status, required this.loading}) + : super._() { BuiltValueNullFieldError.checkNotNull(status, 'WalletTransfer', 'status'); BuiltValueNullFieldError.checkNotNull(loading, 'WalletTransfer', 'loading'); } @@ -57,20 +58,20 @@ class _$WalletTransfer extends WalletTransfer { class WalletTransferBuilder implements Builder { - _$WalletTransfer _$v; + _$WalletTransfer? _$v; - ListBuilder _errors; + ListBuilder? _errors; ListBuilder get errors => _$this._errors ??= new ListBuilder(); - set errors(ListBuilder errors) => _$this._errors = errors; + set errors(ListBuilder? errors) => _$this._errors = errors; - WalletTransferStatus _status; - WalletTransferStatus get status => _$this._status; - set status(WalletTransferStatus status) => _$this._status = status; + WalletTransferStatus? _status; + WalletTransferStatus? get status => _$this._status; + set status(WalletTransferStatus? status) => _$this._status = status; - bool _loading; - bool get loading => _$this._loading; - set loading(bool loading) => _$this._loading = loading; + bool? _loading; + bool? get loading => _$this._loading; + set loading(bool? loading) => _$this._loading = loading; WalletTransferBuilder(); @@ -92,7 +93,7 @@ class WalletTransferBuilder } @override - void update(void Function(WalletTransferBuilder) updates) { + void update(void Function(WalletTransferBuilder)? updates) { if (updates != null) updates(this); } @@ -108,7 +109,7 @@ class WalletTransferBuilder loading: BuiltValueNullFieldError.checkNotNull( loading, 'WalletTransfer', 'loading')); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'errors'; _errors?.build(); diff --git a/lib/qrcode_reader_page.dart b/lib/qrcode_reader_page.dart index 0b7346b..c80073c 100644 --- a/lib/qrcode_reader_page.dart +++ b/lib/qrcode_reader_page.dart @@ -1,19 +1,20 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:etherwallet/utils/scanner_utils.dart'; -import 'package:camera/camera.dart'; -import 'package:firebase_ml_vision/firebase_ml_vision.dart'; -import 'package:flutter/foundation.dart'; +import 'dart:async'; +import 'dart:io'; + import 'package:flutter/material.dart'; -import 'utils/detector_painters.dart'; +import 'package:qr_code_scanner/qr_code_scanner.dart'; -typedef OnScanned = void Function(String address); +typedef OnScanned = void Function(String? address); class QRCodeReaderPage extends StatefulWidget { - QRCodeReaderPage({this.title, this.onScanned, this.closeWhenScanned = true}); - final OnScanned onScanned; + const QRCodeReaderPage({ + Key? key, + required this.title, + this.onScanned, + this.closeWhenScanned = true, + }) : super(key: key); + + final OnScanned? onScanned; final bool closeWhenScanned; final String title; @@ -22,146 +23,81 @@ class QRCodeReaderPage extends StatefulWidget { } class _QRCodeReaderPageState extends State { + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); + QRViewController? controller; static final RegExp _basicAddress = RegExp(r'^(0x)?[0-9a-f]{40}', caseSensitive: false); - List _scanResults; - CameraController _camera; - bool _isDetecting = false; - CameraLensDirection _direction = CameraLensDirection.back; - final BarcodeDetector _barcodeDetector = - FirebaseVision.instance.barcodeDetector(); + StreamSubscription? _subscription; + // In order to get hot reload to work we need to pause the camera if the platform + // is android, or resume the camera if the platform is iOS. @override - void initState() { - super.initState(); - _initializeCamera(); + void reassemble() { + super.reassemble(); + if (Platform.isAndroid) { + controller!.pauseCamera(); + } else if (Platform.isIOS) { + controller!.resumeCamera(); + } } - void _initializeCamera() async { - final CameraDescription description = - await ScannerUtils.getCamera(_direction); + @override + Widget build(BuildContext context) { + final scanArea = (MediaQuery.of(context).size.width < 400 || + MediaQuery.of(context).size.height < 400) + ? 150.0 + : 300.0; - _camera = CameraController( - description, - defaultTargetPlatform == TargetPlatform.iOS - ? ResolutionPreset.low - : ResolutionPreset.medium, - enableAudio: false, + return Scaffold( + body: Column( + children: [ + Expanded( + flex: 5, + child: QRView( + key: qrKey, + onQRViewCreated: _onQRViewCreated, + overlay: QrScannerOverlayShape( + borderColor: Colors.red, + borderRadius: 10, + borderLength: 30, + borderWidth: 10, + cutOutSize: scanArea, + )), + ), + ], + ), ); - await _camera.initialize(); - - _camera.startImageStream((CameraImage image) { - if (_isDetecting) return; - - _isDetecting = true; - - ScannerUtils.detect( - image: image, - detectInImage: _barcodeDetector.detectInImage, - imageRotation: description.sensorOrientation, - ).then((dynamic results) => results as List).then( - (List results) { - setState(() { - _scanResults = results - .where((item) => _basicAddress.hasMatch(item.displayValue)) - .toList(); - }); - }, - ).whenComplete(() { - if (_scanResults.length > 0) { - if (widget.onScanned != null) - widget.onScanned(_scanResults.first.displayValue); - - if (widget.closeWhenScanned) { - _isDetecting = true; // stop looping - - Future.delayed(Duration(seconds: 1), () { - if (Navigator.canPop(context)) { - Navigator.pop(context); - } - }); - - return; - } - } - _isDetecting = false; - }); - }); } - Widget _buildResults() { - if (_scanResults == null || - _camera == null || - !_camera.value.isInitialized) { - return Container(); - } - - final Size imageSize = Size( - _camera.value.previewSize.height, - _camera.value.previewSize.width, - ); + void _onQRViewCreated(QRViewController controller) { + setState(() { + this.controller = controller; + }); - return CustomPaint( - painter: BarcodeDetectorPainter(imageSize, _scanResults), - ); - } + _subscription = controller.scannedDataStream.listen((scanData) { + // metamask qrcode adds "ethereum:" in front of the address. + final address = scanData.code.replaceAll('ethereum:', ''); - Widget _buildImage() { - return Container( - constraints: const BoxConstraints.expand(), - child: _camera == null - ? const Center( - child: Text('Initialising camera, please wait.'), - ) - : Stack( - fit: StackFit.expand, - children: [ - CameraPreview(_camera), - _buildResults(), - ], - ), - ); - } + if (!_basicAddress.hasMatch(address)) { + return; + } - void _toggleCameraDirection() async { - if (_direction == CameraLensDirection.back) { - _direction = CameraLensDirection.front; - } else { - _direction = CameraLensDirection.back; - } + widget.onScanned!(address); - await _camera.stopImageStream(); - await _camera.dispose(); + if (widget.closeWhenScanned) { + _subscription?.cancel(); - setState(() { - _camera = null; + if (Navigator.canPop(context)) { + Navigator.pop(context); + } + } }); - - _initializeCamera(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: _buildImage(), - floatingActionButton: FloatingActionButton( - onPressed: _toggleCameraDirection, - child: _direction == CameraLensDirection.back - ? const Icon(Icons.camera_front) - : const Icon(Icons.camera_rear), - ), - ); } @override void dispose() { - _camera.dispose().then((_) { - _barcodeDetector.close(); - }); + controller?.dispose(); super.dispose(); } diff --git a/lib/router.dart b/lib/router.dart index 4def5bd..b628435 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -8,44 +8,42 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:provider/provider.dart'; -import 'context/wallet/wallet_provider.dart'; import 'context/setup/wallet_setup_provider.dart'; import 'context/transfer/wallet_transfer_provider.dart'; +import 'context/wallet/wallet_provider.dart'; import 'intro_page.dart'; Map getRoutes(context) { return { '/': (BuildContext context) { - var configurationService = Provider.of(context); + final configurationService = Provider.of(context); if (configurationService.didSetupWallet()) - return WalletProvider(builder: (context, store) { - return WalletMainPage("Your wallet"); - }); + return WalletProvider( + // ignore: prefer_const_constructors + builder: (context, store) => WalletMainPage('Your wallet')); - return IntroPage(); + return const IntroPage(); }, '/create': (BuildContext context) => WalletSetupProvider(builder: (context, store) { useEffect(() { store.generateMnemonic(); - return null; }, []); - return WalletCreatePage("Create wallet"); + // ignore: prefer_const_constructors + return WalletCreatePage('Create wallet'); }), '/import': (BuildContext context) => WalletSetupProvider( - builder: (context, store) { - return WalletImportPage("Import wallet"); - }, + // ignore: prefer_const_constructors + builder: (context, store) => WalletImportPage('Import wallet'), ), '/transfer': (BuildContext context) => WalletTransferProvider( - builder: (context, store) { - return WalletTransferPage(title: "Send Tokens"); - }, + // ignore: prefer_const_constructors + builder: (context, store) => WalletTransferPage(title: 'Send Tokens'), ), '/qrcode_reader': (BuildContext context) => QRCodeReaderPage( - title: "Scan QRCode", - onScanned: ModalRoute.of(context).settings.arguments, + title: 'Scan QRCode', + onScanned: ModalRoute.of(context)?.settings.arguments as OnScanned?, ) }; } diff --git a/lib/service/address_service.dart b/lib/service/address_service.dart index 0ee0885..38447a8 100644 --- a/lib/service/address_service.dart +++ b/lib/service/address_service.dart @@ -1,12 +1,13 @@ import 'package:etherwallet/service/configuration_service.dart'; import 'package:bip39/bip39.dart' as bip39; -import 'package:etherwallet/utils/hd_key.dart'; -import "package:hex/hex.dart"; +import 'package:ed25519_hd_key/ed25519_hd_key.dart'; +import 'package:hex/hex.dart'; +import 'package:convert/convert.dart'; import 'package:web3dart/credentials.dart'; abstract class IAddressService { String generateMnemonic(); - String getPrivateKey(String mnemonic); + Future getPrivateKey(String mnemonic); Future getPublicAddress(String privateKey); Future setupFromMnemonic(String mnemonic); Future setupFromPrivateKey(String privateKey); @@ -14,24 +15,27 @@ abstract class IAddressService { } class AddressService implements IAddressService { - IConfigurationService _configService; - AddressService(this._configService); + const AddressService(this._configService); + + final IConfigurationService _configService; @override String generateMnemonic() { return bip39.generateMnemonic(); } + @override String entropyToMnemonic(String entropyMnemonic) { return bip39.entropyToMnemonic(entropyMnemonic); } @override - String getPrivateKey(String mnemonic) { - String seed = bip39.mnemonicToSeedHex(mnemonic); - KeyData master = HDKey.getMasterKeyFromSeed(seed); + Future getPrivateKey(String mnemonic) async { + final seed = bip39.mnemonicToSeedHex(mnemonic); + final master = await ED25519_HD_KEY.getMasterKeyFromSeed(hex.decode(seed), + masterSecret: 'Bitcoin seed'); final privateKey = HEX.encode(master.key); - print("private: $privateKey"); + print('private: $privateKey'); return privateKey; } @@ -40,14 +44,14 @@ class AddressService implements IAddressService { final private = EthPrivateKey.fromHex(privateKey); final address = await private.extractAddress(); - print("address: $address"); + print('address: $address'); return address; } @override Future setupFromMnemonic(String mnemonic) async { final cryptMnemonic = bip39.mnemonicToEntropy(mnemonic); - final privateKey = this.getPrivateKey(mnemonic); + final privateKey = await getPrivateKey(mnemonic); await _configService.setMnemonic(cryptMnemonic); await _configService.setPrivateKey(privateKey); diff --git a/lib/service/configuration_service.dart b/lib/service/configuration_service.dart index 7b869fd..fd5d614 100644 --- a/lib/service/configuration_service.dart +++ b/lib/service/configuration_service.dart @@ -1,46 +1,47 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class IConfigurationService { - Future setMnemonic(String value); + Future setMnemonic(String? value); Future setupDone(bool value); - Future setPrivateKey(String value); - String getMnemonic(); - String getPrivateKey(); + Future setPrivateKey(String? value); + String? getMnemonic(); + String? getPrivateKey(); bool didSetupWallet(); } class ConfigurationService implements IConfigurationService { - SharedPreferences _preferences; - ConfigurationService(this._preferences); + const ConfigurationService(this._preferences); + + final SharedPreferences _preferences; @override - Future setMnemonic(String value) async { - await _preferences.setString("mnemonic", value ?? ""); + Future setMnemonic(String? value) async { + await _preferences.setString('mnemonic', value ?? ''); } @override - Future setPrivateKey(String value) async { - await _preferences.setString("privateKey", value ?? ""); + Future setPrivateKey(String? value) async { + await _preferences.setString('privateKey', value ?? ''); } @override Future setupDone(bool value) async { - await _preferences.setBool("didSetupWallet", value); + await _preferences.setBool('didSetupWallet', value); } // gets @override - String getMnemonic() { - return _preferences.getString("mnemonic"); + String? getMnemonic() { + return _preferences.getString('mnemonic'); } @override - String getPrivateKey() { - return _preferences.getString("privateKey"); + String? getPrivateKey() { + return _preferences.getString('privateKey'); } @override bool didSetupWallet() { - return _preferences.getBool("didSetupWallet") ?? false; + return _preferences.getBool('didSetupWallet') ?? false; } } diff --git a/lib/service/contract_service.dart b/lib/service/contract_service.dart index dfaac6c..4cb36ab 100644 --- a/lib/service/contract_service.dart +++ b/lib/service/contract_service.dart @@ -2,13 +2,16 @@ import 'dart:async'; import 'package:web3dart/web3dart.dart'; typedef TransferEvent = void Function( - EthereumAddress from, EthereumAddress to, BigInt value); + EthereumAddress from, + EthereumAddress to, + BigInt value, +); abstract class IContractService { Future getCredentials(String privateKey); - Future send( + Future send( String privateKey, EthereumAddress receiver, BigInt amount, - {TransferEvent onTransfer, Function onError}); + {TransferEvent? onTransfer, Function(Object exeception)? onError}); Future getTokenBalance(EthereumAddress from); Future getEthBalance(EthereumAddress from); Future dispose(); @@ -25,22 +28,24 @@ class ContractService implements IContractService { ContractFunction _balanceFunction() => contract.function('balanceOf'); ContractFunction _sendFunction() => contract.function('transfer'); + @override Future getCredentials(String privateKey) => client.credentialsFromPrivateKey(privateKey); - Future send( + @override + Future send( String privateKey, EthereumAddress receiver, BigInt amount, - {TransferEvent onTransfer, Function onError}) async { - final credentials = await this.getCredentials(privateKey); + {TransferEvent? onTransfer, Function(Object exeception)? onError}) async { + final credentials = await getCredentials(privateKey); final from = await credentials.extractAddress(); final networkId = await client.getNetworkId(); - StreamSubscription event; + StreamSubscription? event; // Workaround once sendTransacton doesn't return a Promise containing confirmation / receipt if (onTransfer != null) { event = listenTransfer((from, to, value) async { onTransfer(from, to, value); - await event.cancel(); + await event?.cancel(); }, take: 1); } @@ -65,12 +70,14 @@ class ContractService implements IContractService { } } + @override Future getEthBalance(EthereumAddress from) async { - return await client.getBalance(from); + return client.getBalance(from); } + @override Future getTokenBalance(EthereumAddress from) async { - var response = await client.call( + final response = await client.call( contract: contract, function: _balanceFunction(), params: [from], @@ -79,7 +86,8 @@ class ContractService implements IContractService { return response.first as BigInt; } - StreamSubscription listenTransfer(TransferEvent onTransfer, {int take}) { + @override + StreamSubscription listenTransfer(TransferEvent onTransfer, {int? take}) { var events = client.events(FilterOptions.events( contract: contract, event: _transferEvent(), @@ -90,7 +98,12 @@ class ContractService implements IContractService { } return events.listen((event) { - final decoded = _transferEvent().decodeResults(event.topics, event.data); + if (event.topics == null || event.data == null) { + return; + } + + final decoded = + _transferEvent().decodeResults(event.topics!, event.data!); final from = decoded[0] as EthereumAddress; final to = decoded[1] as EthereumAddress; @@ -104,6 +117,7 @@ class ContractService implements IContractService { }); } + @override Future dispose() async { await client.dispose(); } diff --git a/lib/services_provider.dart b/lib/services_provider.dart index 7b77af0..8b7626e 100644 --- a/lib/services_provider.dart +++ b/lib/services_provider.dart @@ -18,7 +18,9 @@ Future> createProviders(AppConfigParams params) async { final sharedPrefs = await SharedPreferences.getInstance(); final configurationService = ConfigurationService(sharedPrefs); + final addressService = AddressService(configurationService); + final contract = await ContractParser.fromAssets( 'TargaryenCoin.json', params.contractAddress); diff --git a/lib/utils/contract_parser.dart b/lib/utils/contract_parser.dart index 39f302a..11cb005 100644 --- a/lib/utils/contract_parser.dart +++ b/lib/utils/contract_parser.dart @@ -10,8 +10,8 @@ class ContractParser { jsonDecode(await rootBundle.loadString('assets/TargaryenCoin.json')); return DeployedContract( - ContractAbi.fromJson( - jsonEncode(contractJson["abi"]), contractJson["contractName"]), + ContractAbi.fromJson(jsonEncode(contractJson['abi']), + contractJson['contractName'] as String), EthereumAddress.fromHex(contractAddress)); } } diff --git a/lib/utils/detector_painters.dart b/lib/utils/detector_painters.dart deleted file mode 100644 index edf6189..0000000 --- a/lib/utils/detector_painters.dart +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:firebase_ml_vision/firebase_ml_vision.dart'; -import 'package:flutter/material.dart'; - -enum Detector { barcode } - -class BarcodeDetectorPainter extends CustomPainter { - BarcodeDetectorPainter(this.absoluteImageSize, this.barcodeLocations); - - final Size absoluteImageSize; - final List barcodeLocations; - - @override - void paint(Canvas canvas, Size size) { - final double scaleX = size.width / absoluteImageSize.width; - final double scaleY = size.height / absoluteImageSize.height; - - Rect scaleRect(Barcode barcode) { - return Rect.fromLTRB( - barcode.boundingBox.left * scaleX, - barcode.boundingBox.top * scaleY, - barcode.boundingBox.right * scaleX, - barcode.boundingBox.bottom * scaleY, - ); - } - - final Paint paint = Paint() - ..style = PaintingStyle.stroke - ..strokeWidth = 2.0; - - for (Barcode barcode in barcodeLocations) { - paint.color = Colors.green; - canvas.drawRect(scaleRect(barcode), paint); - } - } - - @override - bool shouldRepaint(BarcodeDetectorPainter oldDelegate) { - return oldDelegate.absoluteImageSize != absoluteImageSize || - oldDelegate.barcodeLocations != barcodeLocations; - } -} diff --git a/lib/utils/eth_address_formatter.dart b/lib/utils/eth_address_formatter.dart index 0031121..8674c8a 100644 --- a/lib/utils/eth_address_formatter.dart +++ b/lib/utils/eth_address_formatter.dart @@ -2,6 +2,6 @@ class EthAddressFormatter { EthAddressFormatter(this.address); final String address; String mask() { - return "${address.substring(0, 6)}...${address.substring(address.length - 6, address.length)}"; + return '${address.substring(0, 6)}...${address.substring(address.length - 6, address.length)}'; } } diff --git a/lib/utils/eth_amount_formatter.dart b/lib/utils/eth_amount_formatter.dart index 733ea90..adf59bd 100644 --- a/lib/utils/eth_amount_formatter.dart +++ b/lib/utils/eth_amount_formatter.dart @@ -3,13 +3,15 @@ import 'package:web3dart/web3dart.dart'; class EthAmountFormatter { EthAmountFormatter(this.amount); - final BigInt amount; + final BigInt? amount; String format({ - fromUnit = EtherUnit.wei, - toUnit = EtherUnit.ether, + EtherUnit fromUnit = EtherUnit.wei, + EtherUnit toUnit = EtherUnit.ether, }) { - if (amount == null) return "-"; - + if (amount == null) { + return '-'; + } + return EtherAmount.fromUnitAndValue(fromUnit, amount) .getValueInUnit(toUnit) .toString(); diff --git a/lib/utils/hd_key.dart b/lib/utils/hd_key.dart deleted file mode 100644 index 1fcb12f..0000000 --- a/lib/utils/hd_key.dart +++ /dev/null @@ -1,78 +0,0 @@ -/* -* author: Aleksey Popov -* homepage: https://github.com/alepop/dart-ed25519-hd-key -*/ - -import 'dart:convert'; -import 'dart:typed_data'; -import 'package:tweetnacl/tweetnacl.dart' as ED25519; -import 'package:pointycastle/digests/sha512.dart'; -import 'package:pointycastle/macs/hmac.dart'; -import 'package:pointycastle/api.dart'; -import 'package:hex/hex.dart'; - -class KeyData { - List key; - List chainCode; - KeyData({this.key, this.chainCode}); -} - -const String MASTER_SECRET = 'Bitcoin seed'; -const int HARDENED_OFFSET = 0x80000000; - -class _HDKey { - static final _curveBytes = utf8.encode(MASTER_SECRET); - static final _pathRegex = RegExp(r"^(m\/)?(\d+'?\/)*\d+'?$"); - - const _HDKey(); - - KeyData _getKeys(Uint8List data, Uint8List keyParameter) { - final digest = SHA512Digest(); - final hmac = HMac(digest, 128)..init(KeyParameter(keyParameter)); - final I = hmac.process(data); - final IL = I.sublist(0, 32); - final IR = I.sublist(32); - return KeyData(key: IL, chainCode: IR); - } - - KeyData _getCKDPriv(KeyData data, int index) { - Uint8List dataBytes = Uint8List(37); - dataBytes[0] = 0x00; - dataBytes.setRange(1, 33, data.key); - dataBytes.buffer.asByteData().setUint32(33, index); - return this._getKeys(dataBytes, data.chainCode); - } - - KeyData getMasterKeyFromSeed(String seed) { - final seedBytes = HEX.decode(seed); - return this._getKeys(seedBytes, _HDKey._curveBytes); - } - - Uint8List getBublickKey(Uint8List privateKey, [bool withZeroByte = true]) { - final signature = ED25519.Signature.keyPair_fromSeed(privateKey); - if (withZeroByte == true) { - Uint8List dataBytes = Uint8List(33); - dataBytes[0] = 0x00; - dataBytes.setRange(1, 33, signature.publicKey); - return dataBytes; - } else { - return signature.publicKey; - } - } - - KeyData derivePath(String path, String seed) { - if (!_HDKey._pathRegex.hasMatch(path)) - throw ArgumentError( - "Invalid derivation path. Expected BIP32 path format"); - KeyData master = this.getMasterKeyFromSeed(seed); - List segments = path.split('/'); - segments = segments.sublist(1); - - return segments.fold(master, (prevKeyData, indexStr) { - int index = int.parse(indexStr.substring(0, indexStr.length - 1)); - return this._getCKDPriv(prevKeyData, index + HARDENED_OFFSET); - }); - } -} - -const HDKey = const _HDKey(); diff --git a/lib/utils/scanner_utils.dart b/lib/utils/scanner_utils.dart deleted file mode 100644 index 6bd1564..0000000 --- a/lib/utils/scanner_utils.dart +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:camera/camera.dart'; -import 'package:firebase_ml_vision/firebase_ml_vision.dart'; -import 'package:flutter/foundation.dart'; - -class ScannerUtils { - ScannerUtils._(); - - static Future getCamera(CameraLensDirection dir) async { - return await availableCameras().then( - (List cameras) => cameras.firstWhere( - (CameraDescription camera) => camera.lensDirection == dir, - ), - ); - } - - static Future detect({ - @required CameraImage image, - @required Future Function(FirebaseVisionImage image) detectInImage, - @required int imageRotation, - }) async { - return detectInImage( - FirebaseVisionImage.fromBytes( - _concatenatePlanes(image.planes), - _buildMetaData(image, _rotationIntToImageRotation(imageRotation)), - ), - ); - } - - static Uint8List _concatenatePlanes(List planes) { - final WriteBuffer allBytes = WriteBuffer(); - for (Plane plane in planes) { - allBytes.putUint8List(plane.bytes); - } - return allBytes.done().buffer.asUint8List(); - } - - static FirebaseVisionImageMetadata _buildMetaData( - CameraImage image, - ImageRotation rotation, - ) { - return FirebaseVisionImageMetadata( - rawFormat: image.format.raw, - size: Size(image.width.toDouble(), image.height.toDouble()), - rotation: rotation, - planeData: image.planes.map( - (Plane plane) { - return FirebaseVisionImagePlaneMetadata( - bytesPerRow: plane.bytesPerRow, - height: plane.height, - width: plane.width, - ); - }, - ).toList(), - ); - } - - static ImageRotation _rotationIntToImageRotation(int rotation) { - switch (rotation) { - case 0: - return ImageRotation.rotation0; - case 90: - return ImageRotation.rotation90; - case 180: - return ImageRotation.rotation180; - default: - assert(rotation == 270); - return ImageRotation.rotation270; - } - } -} diff --git a/lib/utils/wallet_icons.dart b/lib/utils/wallet_icons.dart index 88e9492..76782ed 100644 --- a/lib/utils/wallet_icons.dart +++ b/lib/utils/wallet_icons.dart @@ -1,5 +1,5 @@ /// Flutter icons MyFlutterApp -/// Copyright (C) 2020 by original authors @ fluttericon.com, fontello.com +/// Copyright (C) 2021 by original authors @ fluttericon.com, fontello.com /// This font was generated by FlutterIcon.com, which is derived from Fontello. /// /// To use this font, place it in your fonts/ directory and include the @@ -23,8 +23,10 @@ class WalletIcons { WalletIcons._(); static const _kFontFam = 'MyFlutterApp'; - static const _kFontPkg = null; + static const String? _kFontPkg = null; + static const IconData key = + IconData(0xf084, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData gem = IconData(0xf3a5, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData ethereum = diff --git a/lib/wallet_create_page.dart b/lib/wallet_create_page.dart index 565be6f..4ca0f8f 100644 --- a/lib/wallet_create_page.dart +++ b/lib/wallet_create_page.dart @@ -7,12 +7,13 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'components/wallet/display_mnemonic.dart'; class WalletCreatePage extends HookWidget { - WalletCreatePage(this.title); + const WalletCreatePage(this.title, {Key? key}) : super(key: key); final String title; + @override Widget build(BuildContext context) { - var store = useWalletSetup(context); + final store = useWalletSetup(context); return Scaffold( appBar: AppBar( @@ -20,18 +21,17 @@ class WalletCreatePage extends HookWidget { ), body: store.state.step == WalletCreateSteps.display ? DisplayMnemonic( - mnemonic: store.state.mnemonic, + mnemonic: store.state.mnemonic!, onNext: () async { store.goto(WalletCreateSteps.confirm); }, ) : ConfirmMnemonic( - mnemonic: store.state.mnemonic, - errors: store.state.errors.toList(), + errors: store.state.errors?.toList(), onConfirm: !store.state.loading ? (confirmedMnemonic) async { if (await store.confirmMnemonic(confirmedMnemonic)) { - Navigator.of(context).popAndPushNamed("/"); + Navigator.of(context).popAndPushNamed('/'); } } : null, diff --git a/lib/wallet_import_page.dart b/lib/wallet_import_page.dart index 07b3a7d..4eb8a78 100644 --- a/lib/wallet_import_page.dart +++ b/lib/wallet_import_page.dart @@ -5,32 +5,37 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class WalletImportPage extends HookWidget { - WalletImportPage(this.title); + const WalletImportPage(this.title, {Key? key}) : super(key: key); final String title; + @override Widget build(BuildContext context) { - var store = useWalletSetup(context); + final store = useWalletSetup(context); return Scaffold( appBar: AppBar( title: Text(title), ), body: ImportWalletForm( - errors: store.state.errors.toList(), + errors: store.state.errors?.toList(), onImport: !store.state.loading ? (type, value) async { switch (type) { case WalletImportType.mnemonic: - if (!await store.importFromMnemonic(value)) return; + if (!await store.importFromMnemonic(value)) { + return; + } break; case WalletImportType.privateKey: - if (!await store.importFromPrivateKey(value)) return; + if (!await store.importFromPrivateKey(value)) { + return; + } break; default: break; } - Navigator.of(context).popAndPushNamed("/"); + Navigator.of(context).popAndPushNamed('/'); } : null, ), diff --git a/lib/wallet_main_page.dart b/lib/wallet_main_page.dart index 0be707f..99aaf05 100644 --- a/lib/wallet_main_page.dart +++ b/lib/wallet_main_page.dart @@ -1,18 +1,20 @@ import 'package:etherwallet/components/wallet/balance.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; + import 'components/dialog/alert.dart'; import 'components/menu/main_menu.dart'; import 'context/wallet/wallet_provider.dart'; class WalletMainPage extends HookWidget { - WalletMainPage(this.title); + const WalletMainPage(this.title, {Key? key}) : super(key: key); final String title; @override Widget build(BuildContext context) { - var store = useWallet(context); + final store = useWallet(context); useEffect(() { store.initialise(); @@ -22,37 +24,52 @@ class WalletMainPage extends HookWidget { return Scaffold( drawer: MainMenu( address: store.state.address, - onReset: () async { - Alert( - title: "Warning", - text: - "Without your seed phrase or private key you cannot restore your wallet balance", - actions: [ - TextButton( - child: Text("cancel"), - onPressed: () => Navigator.of(context).pop(), - ), - TextButton( - child: Text("reset"), - onPressed: () async { - await store.resetWallet(); - Navigator.popAndPushNamed(context, "/"); - }, - ) - ]).show(context); - }, + onReset: () => Alert( + title: 'Warning', + text: + 'Without your seed phrase or private key you cannot restore your wallet balance', + actions: [ + TextButton( + child: const Text('cancel'), + onPressed: () => Navigator.of(context).pop(), + ), + TextButton( + child: const Text('reset'), + onPressed: () async { + await store.resetWallet(); + Navigator.popAndPushNamed(context, '/'); + }, + ) + ]).show(context), + onRevealKey: () => Alert( + title: 'Private key', + text: + 'WARNING: In production environment the private key should be protected with password.\r\n\r\n${store.getPrivateKey() ?? "-"}', + actions: [ + TextButton( + child: const Text('close'), + onPressed: () => Navigator.of(context).pop(), + ), + TextButton( + child: const Text('copy and close'), + onPressed: () { + Clipboard.setData(ClipboardData(text: store.getPrivateKey())); + Navigator.of(context).pop(); + }, + ), + ]).show(context), ), appBar: AppBar( title: Text(title), actions: [ Builder( builder: (context) => IconButton( - icon: Icon(Icons.refresh), + icon: const Icon(Icons.refresh), onPressed: !store.state.loading ? () async { await store.fetchOwnBalance(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text("Balance updated"), + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Balance updated'), duration: Duration(milliseconds: 800), )); } @@ -60,9 +77,9 @@ class WalletMainPage extends HookWidget { ), ), IconButton( - icon: Icon(Icons.send), + icon: const Icon(Icons.send), onPressed: () { - Navigator.of(context).pushNamed("/transfer"); + Navigator.of(context).pushNamed('/transfer'); }, ), ], diff --git a/lib/wallet_transfer_page.dart b/lib/wallet_transfer_page.dart index e657a7c..95ab5a0 100644 --- a/lib/wallet_transfer_page.dart +++ b/lib/wallet_transfer_page.dart @@ -6,26 +6,27 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'components/wallet/loading.dart'; class WalletTransferPage extends HookWidget { - WalletTransferPage({@required this.title}); + const WalletTransferPage({Key? key, required this.title}) : super(key: key); final String title; @override Widget build(BuildContext context) { - var transferStore = useWalletTransfer(context); - var qrcodeAddress = useState(); + final transferStore = useWalletTransfer(context); + final qrcodeAddress = useState(''); return Scaffold( + key: key, appBar: AppBar( title: Text(title), actions: [ IconButton( - icon: Icon(Icons.camera_alt), + icon: const Icon(Icons.camera_alt), onPressed: !transferStore.state.loading ? () { Navigator.of(context).pushNamed( - "/qrcode_reader", - arguments: (scannedAddress) async { + '/qrcode_reader', + arguments: (scannedAddress) { qrcodeAddress.value = scannedAddress.toString(); }, ); @@ -35,11 +36,11 @@ class WalletTransferPage extends HookWidget { ], ), body: transferStore.state.loading - ? Loading() + ? const Loading() : TransferForm( address: qrcodeAddress.value, onSubmit: (address, amount) async { - var success = await transferStore.transfer(address, amount); + final success = await transferStore.transfer(address, amount); if (success) { Navigator.popUntil(context, ModalRoute.withName('/')); diff --git a/pubspec.lock b/pubspec.lock index 32ad834..5d777a2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,21 +7,21 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "14.0.0" + version: "21.0.0" analyzer: - dependency: "direct overridden" + dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.41.2" + version: "1.5.0" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.6.0" + version: "2.1.0" async: dependency: transitive description: @@ -35,7 +35,7 @@ packages: name: bip39 url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.6" boolean_selector: dependency: transitive description: @@ -49,42 +49,42 @@ packages: name: build url: "https://pub.dartlang.org" source: hosted - version: "1.6.3" + version: "2.0.1" build_config: dependency: transitive description: name: build_config url: "https://pub.dartlang.org" source: hosted - version: "0.4.6" + version: "1.0.0" build_daemon: dependency: transitive description: name: build_daemon url: "https://pub.dartlang.org" source: hosted - version: "2.1.7" + version: "3.0.0" build_resolvers: dependency: transitive description: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "1.5.4" + version: "2.0.1" build_runner: dependency: "direct dev" description: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "1.11.5" + version: "2.0.2" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "6.1.10" + version: "7.0.0" built_collection: dependency: "direct main" description: @@ -98,28 +98,14 @@ packages: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.0.0" + version: "8.0.6" built_value_generator: dependency: "direct dev" description: name: built_value_generator url: "https://pub.dartlang.org" source: hosted - version: "8.0.0" - camera: - dependency: "direct main" - description: - name: camera - url: "https://pub.dartlang.org" - source: hosted - version: "0.8.0" - camera_platform_interface: - dependency: transitive - description: - name: camera_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" + version: "8.0.6" characters: dependency: transitive description: @@ -140,14 +126,14 @@ packages: name: checked_yaml url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.1" cli_util: dependency: transitive description: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.3.0" clock: dependency: transitive description: @@ -161,7 +147,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "3.6.0" + version: "4.0.0" collection: dependency: transitive description: @@ -175,35 +161,42 @@ packages: name: convert url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - cross_file: + version: "3.0.0" + crypto: dependency: transitive description: - name: cross_file + name: crypto url: "https://pub.dartlang.org" source: hosted - version: "0.3.1" - crypto: + version: "3.0.1" + cryptography: dependency: transitive description: - name: crypto + name: cryptography url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.0.1" cupertino_icons: dependency: "direct main" description: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.3" dart_style: dependency: transitive description: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.3.6" + version: "2.0.1" + ed25519_hd_key: + dependency: "direct main" + description: + name: ed25519_hd_key + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" fake_async: dependency: transitive description: @@ -231,37 +224,51 @@ packages: name: firebase url: "https://pub.dartlang.org" source: hosted - version: "7.3.3" + version: "9.0.1" firebase_analytics: dependency: "direct main" description: name: firebase_analytics url: "https://pub.dartlang.org" source: hosted - version: "5.0.16" + version: "8.0.4" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "2.0.1" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.1" - firebase_ml_vision: - dependency: "direct main" + version: "0.3.0+1" + firebase_core: + dependency: transitive + description: + name: firebase_core + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + firebase_core_web: + dependency: transitive description: - name: firebase_ml_vision + name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "0.9.10" + version: "1.0.3" fixnum: - dependency: "direct overridden" + dependency: transitive description: name: fixnum url: "https://pub.dartlang.org" @@ -278,14 +285,14 @@ packages: name: flutter_hooks url: "https://pub.dartlang.org" source: hosted - version: "0.15.0" + version: "0.16.0" flutter_spinkit: dependency: "direct main" description: name: flutter_spinkit url: "https://pub.dartlang.org" source: hosted - version: "4.1.2+1" + version: "5.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -296,48 +303,55 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" glob: dependency: transitive description: name: glob url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" graphs: dependency: transitive description: name: graphs url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "2.0.0" hex: dependency: "direct main" description: name: hex url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.2.0" http: dependency: transitive description: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.2" + version: "0.13.3" http_multi_server: dependency: transitive description: name: http_multi_server url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "3.0.1" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" + version: "4.0.0" intl: dependency: "direct main" description: @@ -351,14 +365,7 @@ packages: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.5" - isolate: - dependency: transitive - description: - name: isolate - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.3" + version: "1.0.0" js: dependency: transitive description: @@ -372,28 +379,35 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" json_rpc_2: dependency: transitive description: name: json_rpc_2 url: "https://pub.dartlang.org" source: hosted - version: "2.2.2" + version: "3.0.1" json_serializable: dependency: "direct dev" description: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "4.0.2" + version: "4.1.1" + lint: + dependency: "direct dev" + description: + name: lint + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.3" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.4" + version: "1.0.1" matcher: dependency: transitive description: @@ -414,21 +428,21 @@ packages: name: mime url: "https://pub.dartlang.org" source: hosted - version: "0.9.7" + version: "1.0.0" nested: dependency: transitive description: name: nested url: "https://pub.dartlang.org" source: hosted - version: "0.0.4" + version: "1.0.0" package_config: dependency: transitive description: name: package_config url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "2.0.0" path: dependency: transitive description: @@ -449,14 +463,14 @@ packages: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" pedantic: dependency: transitive description: @@ -479,75 +493,82 @@ packages: source: hosted version: "2.0.0" pointycastle: - dependency: "direct main" + dependency: transitive description: name: pointycastle url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "3.0.1" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.5.0" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.1.0" + version: "4.2.1" provider: dependency: "direct main" description: name: provider url: "https://pub.dartlang.org" source: hosted - version: "4.3.3" + version: "5.0.0" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" + version: "2.0.0" pubspec_parse: dependency: transitive description: name: pubspec_parse url: "https://pub.dartlang.org" source: hosted - version: "0.1.8" + version: "1.0.0" qr: dependency: transitive description: name: qr url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "2.0.0" + qr_code_scanner: + dependency: "direct main" + description: + name: qr_code_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0" qr_flutter: dependency: "direct main" description: name: qr_flutter url: "https://pub.dartlang.org" source: hosted - version: "3.2.0" + version: "4.0.0" quiver: - dependency: "direct overridden" + dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.5" shared_preferences_linux: dependency: transitive description: @@ -589,14 +610,14 @@ packages: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.9" + version: "1.1.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.4+1" + version: "1.0.1" sky_engine: dependency: transitive description: flutter @@ -608,14 +629,14 @@ packages: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "0.9.10+3" + version: "1.0.0" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" stack_trace: dependency: transitive description: @@ -664,14 +685,7 @@ packages: name: timing url: "https://pub.dartlang.org" source: hosted - version: "0.1.1+3" - tweetnacl: - dependency: "direct main" - description: - name: tweetnacl - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.2" + version: "1.0.0" typed_data: dependency: transitive description: @@ -685,7 +699,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.2" + version: "6.0.3" url_launcher_linux: dependency: transitive description: @@ -727,7 +741,7 @@ packages: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "2.2.2" + version: "3.0.4" vector_math: dependency: transitive description: @@ -741,28 +755,28 @@ packages: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "0.9.7+15" + version: "1.0.0" web3dart: dependency: "direct main" description: name: web3dart url: "https://pub.dartlang.org" source: hosted - version: "1.2.3" + version: "2.1.0" web_socket_channel: dependency: "direct main" description: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "2.1.0" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.5" xdg_directories: dependency: transitive description: @@ -776,7 +790,7 @@ packages: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "3.1.0" sdks: - dart: ">=2.12.0-259.9.beta <3.0.0" - flutter: ">=1.22.0" + dart: ">=2.12.0 <3.0.0" + flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 0c7d851..3b7815c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,8 @@ name: etherwallet -description: A new Flutter project. +description: Ethereum wallet using an ERC-20 smart contract. +homepage: https://github.com/allanclempe/ether-wallet-flutter +authors: + - "Allan Clempe" # The following line prevents the package from being accidentally published to # pub.dev using `pub publish`. This is preferred for private packages. @@ -15,10 +18,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.3.0+6 +version: 2.0.0+7 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: @@ -28,38 +31,32 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.0 - web3dart: ^1.2.3 - provider: ^4.3.3 - qr_flutter: ^3.2.0 - bip39: ^1.0.3 - tweetnacl: ^0.3.2 - pointycastle: ^1.0.1 - hex: ^0.1.2 + web3dart: ^2.1.0 + provider: ^5.0.0 + qr_flutter: ^4.0.0 + bip39: ^1.0.6 + hex: ^0.2.0 shared_preferences: ^2.0.0 - camera: ^0.8.0 - firebase_ml_vision: ^0.9.10 - web_socket_channel: ^1.1.0 + web_socket_channel: ^2.0.0 intl: ^0.16.1 - flutter_spinkit: "^4.1.1+1" - firebase_analytics: ^5.0.11 + flutter_spinkit: ^5.0.0 + qr_code_scanner: ^0.4.0 + firebase_analytics: ^8.0.4 url_launcher: ^6.0.2 - flutter_hooks: ^0.15.0 - built_value: ^8.0.0 + flutter_hooks: ^0.16.0 + built_value: ^8.0.6 built_collection: ^5.0.0 + ed25519_hd_key: ^2.1.0 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^1.11.2 - built_value_generator: ^8.0.0 + lint: ^1.0.0 + build_runner: ^2.0.2 + built_value_generator: ^8.0.6 json_serializable: ^4.0.2 -dependency_overrides: - analyzer: 0.41.2 - quiver: ^3.0.0 - fixnum: ^1.0.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/configuration_service_mock.dart b/test/configuration_service_mock.dart new file mode 100644 index 0000000..bda50de --- /dev/null +++ b/test/configuration_service_mock.dart @@ -0,0 +1,39 @@ +import 'package:etherwallet/service/configuration_service.dart'; + +class ConfigServiceMock implements IConfigurationService { + @override + bool didSetupWallet() { + // TODO: implement didSetupWallet + throw UnimplementedError(); + } + + @override + String? getMnemonic() { + // TODO: implement getMnemonic + throw UnimplementedError(); + } + + @override + String? getPrivateKey() { + // TODO: implement getPrivateKey + throw UnimplementedError(); + } + + @override + Future setMnemonic(String? value) { + // TODO: implement setMnemonic + throw UnimplementedError(); + } + + @override + Future setPrivateKey(String? value) { + // TODO: implement setPrivateKey + throw UnimplementedError(); + } + + @override + Future setupDone(bool value) { + // TODO: implement setupDone + throw UnimplementedError(); + } +} diff --git a/test/hd_key_test.dart b/test/hd_key_test.dart deleted file mode 100644 index b5c689b..0000000 --- a/test/hd_key_test.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:bip39/bip39.dart' as bip39; -import 'package:etherwallet/utils/hd_key.dart'; -import 'package:flutter_test/flutter_test.dart'; -import "package:hex/hex.dart"; - -void main() { - group("Test seed", () { - test("should have valid key", () { - String seed = bip39.mnemonicToSeedHex("thought empty modify achieve arch tooth sign unhappy life tape team dust"); - var master = HDKey.getMasterKeyFromSeed(seed); - expect( - HEX.encode(master.key), - equals( - "1352d9efc5c511f89ff262f913e58a2d42649d47246752790cbce6987e100bfe")); - }); - }); -} diff --git a/test/widget_test.dart b/test/widget_test.dart index e0b0b55..097e4ab 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -8,12 +8,16 @@ import 'package:etherwallet/service/address_service.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'configuration_service_mock.dart'; + void main() { - test('should return private key from mnemonic', () { - final addressService = AddressService(null); - final privateKey = addressService.getPrivateKey( - "loan absorb orange crouch mixed position sweet law ghost habit upgrade toss"); + test('should return private key from mnemonic', () async { + final config = ConfigServiceMock(); + final addressService = AddressService(config); + + final privateKey = await addressService.getPrivateKey( + 'loan absorb orange crouch mixed position sweet law ghost habit upgrade toss'); expect(privateKey, - "02e41a913e0d109672c9122c96f0715ef62746aabe186a8160bca314acaa3178"); + '02e41a913e0d109672c9122c96f0715ef62746aabe186a8160bca314acaa3178'); }); }