Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CW-912 [1/?] one class per file, minor cleanups #12

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
MONERO_C_TAG=v0.18.3.4-RC5
MONERO_C_TAG=v0.18.3.4-RC12
COIN=monero
4 changes: 2 additions & 2 deletions .fvmrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"flutter": "3.24.4"
}
"flutter": "3.29.0"
}
2 changes: 1 addition & 1 deletion .github/workflows/build_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y build-essential pkg-config autoconf libtool ccache make cmake gcc g++ git curl lbzip2 libtinfo5 gperf unzip python-is-python3
sudo apt install -y build-essential pkg-config autoconf libtool ccache make cmake gcc g++ git curl lbzip2 libtinfo5 gperf unzip python-is-python3 llvm
- name: setup ccache
uses: hendrikmuhs/[email protected]
with:
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
Expand Down Expand Up @@ -46,4 +48,8 @@ app.*.map.json
lib/l10n/*.dart
lib/generated/
lib/gen/*.dart
missing_translations.txt
missing_translations.txt

# FVM Version Cache
.fvm/
*.g.dart
25 changes: 15 additions & 10 deletions .tooling/format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@
set -x -e
cd "$(dirname "$0")"
cd ..
dart run build_runner build
pushd lib
for dir in coins themes utils view_model views widgets;
do
pushd $dir
dart fix --apply
dart format .
popd
dart format main.dart
done

pushd lib/l10n
for file in *.arb;
do
jq 'to_entries
| group_by(.key | sub("^@"; ""))
| map( sort_by(.key | startswith("@")) | map({ (.key): .value }) | add )
| add' $file > $file.tmp || rm $file.tmp
mv $file.tmp $file
done
popd

dart run build_runner build --delete-conflicting-outputs
dart fix --apply .
dart format .

flutter gen-l10n
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dart.flutterSdkPath": ".fvm/versions/3.29.0"
}
22 changes: 4 additions & 18 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
MIT License
Copyright (C) 2025 Cake Labs LLC

Copyright (c) 2024 Cake Labs LLC
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
24 changes: 19 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
include .env
UNAME := $(shell uname)

libs_android_download:
./build_moneroc.sh --prebuild --coin ${COIN} --tag ${MONERO_C_TAG} --triplet x86_64-linux-android --location android/app/src/main/jniLibs/x86_64
./build_moneroc.sh --prebuild --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-linux-android --location android/app/src/main/jniLibs/arm64-v8a
./build_moneroc.sh --prebuild --coin ${COIN} --tag ${MONERO_C_TAG} --triplet armv7a-linux-androideabi --location android/app/src/main/jniLibs/armeabi-v7a

libs_android_build:
[[ ! "x$(shell uname)" == "xLinux" ]] && exit 1 # Only Linux hosts can build for android, try $(MAKE) libs_android_download
ifneq ($(UNAME), Linux)
echo Only Linux hosts can build for android, try $(MAKE) libs_android_download
exit 1
endif
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet x86_64-linux-android --location android/app/src/main/jniLibs/x86_64
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-linux-android --location android/app/src/main/jniLibs/arm64-v8a
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet armv7a-linux-androideabi --location android/app/src/main/jniLibs/armeabi-v7a
Expand All @@ -15,16 +19,26 @@ libs_android_build_ci:
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-linux-android --location android/app/src/main/jniLibs/arm64-v8a

libs_ios_download:
./build_moneroc.sh --prebuild --coin ${COIN} --tag ${MONERO_C_TAG} --triplet host-apple-ios --location ios
./build_moneroc.sh --prebuild --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-apple-ios --location ios/native_libs/ios-arm64
./build_moneroc.sh --prebuild --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-apple-ios --location ios/native_libs/ios-arm64-simulator
cd ios && ./gen_framework.sh

libs_ios_build:
[[ "x$(shell uname)" == "xDarwin" ]] || exit 1 # Only Darwin hosts can build for iOS, try $(MAKE) libs_ios_download
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet host-apple-ios --location ios
ifneq ($(UNAME), Darwin)
echo Only Darwin hosts can build for iOS, try $(MAKE) libs_ios_download
exit 1
endif
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-apple-ios --location ios/native_libs/ios-arm64
./build_moneroc.sh --coin ${COIN} --tag ${MONERO_C_TAG} --triplet aarch64-apple-iossimulator --location ios/native_libs/ios-arm64-simulator
cd ios && ./gen_framework.sh

cupcake_android_monero:
dart run build_runner build
dart run build_runner build --delete-conflicting-outputs
flutter build apk --dart-define=COIN_MONERO=true

cupcake_ios_monero:
dart run build_runner build --delete-conflicting-outputs
flutter build ios --no-codesign --dart-define=COIN_MONERO=true

prepare_dev:
./.tooling/prepare_dev.sh
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
To build:

```bash
$ make libs_android_build # or libs_android_download
$ make prepare_dev # load dev signing key
$ make cupcake_android_monero
$ make libs_android_build # or libs_android_download, libs_ios_build, libs_ios_download
$ make prepare_dev # load dev signing key (not required on iOS)
$ make cupcake_android_monero # or cupcake_
```

### Adding other coins
Expand Down
49 changes: 26 additions & 23 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
analyzer:
errors:
must_be_immutable: ignore
overridden_fields: ignore
exclude:
- '**.g.dart'
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
unawaited_futures: true
avoid_print: false
parameter_assignments: true
prefer_const_declarations: true
prefer_final_fields: true
prefer_final_in_for_each: true
prefer_final_locals: true
prefer_final_parameters: true
avoid_void_async: true
require_trailing_commas: true
sort_child_properties_last: true
sort_constructors_first: true
sort_unnamed_constructors_first: true
unnecessary_async: true
unnecessary_await_in_return: true
unnecessary_string_interpolations: true
always_declare_return_types: true


# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
formatter:
page_width: 100
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class MainActivity : FlutterActivity() {
val packageInfo: PackageInfo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES)
val signatures = packageInfo.signingInfo.apkContentsSigners
if (signatures.isNotEmpty()) {
val signatures = packageInfo.signingInfo?.apkContentsSigners
if (signatures?.isNotEmpty() == true) {
val md = MessageDigest.getInstance("SHA-1")
val publicKey = md.digest(signatures[0].toByteArray())
return Base64.encodeToString(publicKey, Base64.DEFAULT)
Expand All @@ -45,7 +45,7 @@ class MainActivity : FlutterActivity() {
@Suppress("DEPRECATION")
packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
val signatures = packageInfo.signatures
if (signatures.isNotEmpty()) {
if (signatures?.isNotEmpty() == true) {
val md = MessageDigest.getInstance("SHA-1")
val publicKey = md.digest(signatures[0].toByteArray())
return Base64.encodeToString(publicKey, Base64.DEFAULT)
Expand Down
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
2 changes: 1 addition & 1 deletion android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pluginManagement {

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.0" apply false
id "com.android.application" version '8.8.0' apply false
id "org.jetbrains.kotlin.android" version "2.0.21" apply false
}

Expand Down
16 changes: 16 additions & 0 deletions build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
targets:
$default:
builders:
cupcake|rebuild_generator:
generate_for:
include:
- lib/**.dart
- example/**.dart

builders:
rebuild_generator:
import: "package:cupcake/dev/rebuild_generator.dart"
builder_factories: ["rebuildBuilder"]
build_extensions: {".dart": [".g.dart"]}
auto_apply: dependents
build_to: source
67 changes: 67 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Cupcake Notes and Documentation

> This document is intended for developers. If you just want to build Cupcake, please see the top-level `README.md` and `Makefile`.

## Project Structure

Cupcake adheres to a standard project structure; currently, everything resides inside the `lib` directory. This setup may change in the future.

## `lib/coins`

This directory contains the abstract `coin` definition. To add a new currency to Cupcake, simply implement the abstract `Coin` class found here and update `lib/coins/list.dart` with the new class. The app will automatically pick it up, and a new entry will appear on the coin selection screen during creation or restoration.

> **NOTE:** Currently, only one coin is supported. To ensure a smooth user experience, Cupcake will not prompt the user to select an option if there is only one available.

## `lib/dev`

Cupcake's state management is implemented in a very simple way using MVVM. Since the app is designed to work entirely offline, its state doesn't change often. To keep the code simple, I opted to create an in-house state management solution instead of using an existing one-size-fits-all package. While those packages are great, I believe they would be overkill for an app with a minimal UI and limited processing.

This directory contains three code generation utilities that, while entirely optional, make my life much easier and the code much simpler. For example, instead of converting between `ObservableList` and `List` or wrapping widgets to notify about state changes, we simply trigger a rebuild.

### `@GenerateRebuild()`

Place this annotation around a class to ensure that all other generation annotations work correctly.

### `@RebuildOnChange()`

This annotation wraps a variable in a getter and setter that triggers a rebuild when the variable changes.

```dart
@RebuildOnChange()
Barcode? $barcode;
```

You can then use `barcode` (or `viewModel.barcode`), and updating this value will rebuild the UI.

### `@ThrowOnUI(message: "message...", L: "translation_key")`

If you have a function that may throw an error—and that error should be presented to the user in a dismissible manner—use this annotation. It indicates that something went wrong, allowing the user to retry or correct the issue without restarting the entire action.

```dart
@ThrowOnUI(message: "Error handling URQR scan")
Future<void> $handleUR() async {
if (formInvalid) {
throw Exception("The form is invalid");
}
await wallet.handleUR(c!, ur);
}
```

You can use either `message:` or `L:`. The `message:` text will be displayed in plain text, whereas `L:` will use a translation key. The error message will appear as a dismissible alert.

If you do not use `@ThrowOnUI()`, you must wrap the function in a try-catch block. If an error is thrown without being caught, the app will display a panic handler screen that prevents further use.

### `@ExposeRebuildableAccessors()`

This annotation is somewhat special and is designed for the settings page. It exposes all setters and getters from a class instance, making it possible to access them as elements of the ViewModel.

```dart
@ExposeRebuildableAccessors(extraCode: r'$config.save()')
CupcakeConfig get $config => CupcakeConfig.instance;
```

This approach lets you access settings, for example, using `viewModel.configBiometricEnabled`. It may be overkill, but I like it because it essentially removes almost all logic from the settings view model.

## `lib/gen`

The `lib/gen` directory uses `flutter_gen` to access assets. This method is preferable to using string-based paths in UI code, as it prevents accidental typos that might not be caught by the linter or at compile time.
2 changes: 2 additions & 0 deletions ios/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ Runner/GeneratedPluginRegistrant.*

libwallet2_api_c.dylib
MoneroWallet.framework/MoneroWallet
monero_libwallet2_api_c.dylib
MoneroWallet.xcframework
Binary file removed ios/MoneroWallet.framework/Info.plist
Binary file not shown.
16 changes: 8 additions & 8 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/share_plus/ios"

SPEC CHECKSUMS:
fast_scanner: 44c00940355a51258cd6c2085734193cd23d95bc
fast_scanner: 2cb1ad3e69e645e9980fb4961396ce5804caa3e3
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a

PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
Loading
Loading