Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .docker/komodo-wallet-android.dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM komodo/android-sdk:35 AS final

ENV FLUTTER_VERSION="3.35.2"
ENV FLUTTER_VERSION="3.35.3"
ENV HOME="/home/komodo"
ENV USER="komodo"
ENV PATH=$PATH:$HOME/flutter/bin
Expand All @@ -14,4 +14,4 @@ RUN curl -O https://storage.googleapis.com/flutter_infra_release/releases/stable
rm flutter_linux_${FLUTTER_VERSION}-stable.tar.xz && \
flutter config --no-analytics && \
yes "y" | flutter doctor --android-licenses && \
flutter doctor
flutter doctor
2 changes: 1 addition & 1 deletion .github/actions/flutter-deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
uses: subosito/flutter-action@v2
with:
# NB! Keep up-to-date with the flutter version used for development
flutter-version: "3.35.2"
flutter-version: "3.35.3"
channel: "stable"

- name: Prepare build directory
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/roll-sdk-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
# NB! Keep up-to-date with the flutter version used for development
flutter-version: "3.35.2"
flutter-version: "3.35.3"
channel: "stable"

- name: Determine configuration
Expand Down Expand Up @@ -89,7 +89,7 @@ jobs:
echo "SDK packages were successfully rolled"
else
echo "ROLLS_FOUND=false" >> $GITHUB_ENV

if [ -n "${EXIT_CODE}" ] && [ ${EXIT_CODE} -ne 100 ]; then
echo "::warning::SDK package roll script failed with exit code ${EXIT_CODE}"
else
Expand Down
2 changes: 1 addition & 1 deletion app_theme/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ resolution: workspace

environment:
sdk: ">=3.8.1 <4.0.0"
flutter: ">=3.35.2 <4.0.0"
flutter: ">=3.35.3 <4.0.0"

dependencies:
flutter:
Expand Down
6 changes: 3 additions & 3 deletions docs/FLUTTER_VERSION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Supported Flutter Version

This project supports Flutter `3.35.2` (latest stable release). We aim to keep the project up-to-date with the most recent stable Flutter versions.
This project supports Flutter `3.35.3` (latest stable release). We aim to keep the project up-to-date with the most recent stable Flutter versions.

## Recommended Approach: Multiple Flutter Versions

Expand All @@ -15,14 +15,14 @@ See our guide on [Multiple Flutter Versions](MULTIPLE_FLUTTER_VERSIONS.md) for d
While it's possible to pin your global Flutter installation to a specific version, **this approach is not recommended** due to:

- Lack of isolation between projects
- Known issues with `flutter pub get` when using Flutter 3.35.2
- Known issues with `flutter pub get` when using Flutter 3.35.3
- Difficulty switching between versions for different projects

If you still choose to use this method, you can run:

```bash
cd ~/flutter
git checkout 3.35.2
git checkout 3.35.3
flutter doctor
```

Expand Down
16 changes: 8 additions & 8 deletions docs/MULTIPLE_FLUTTER_VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ sudo pacman -R flutter # for Arch

2. Launch Flutter Sidekick

3. Click on "Versions" in the sidebar and download Flutter version `3.35.2`
3. Click on "Versions" in the sidebar and download Flutter version `3.35.3`

4. Set this version as the global default by clicking the "Set as Global" button

Expand Down Expand Up @@ -92,11 +92,11 @@ sudo pacman -R flutter # for Arch
curl -fsSL https://fvm.app/install.sh | bash
```

2. Install and use Flutter 3.35.2:
2. Install and use Flutter 3.35.3:

```bash
fvm install 3.35.2
fvm global 3.35.2
fvm install 3.35.3
fvm global 3.35.3
```

3. Add FVM's default Flutter version to your PATH by adding the following to your `~/.bashrc`, `~/.zshrc`, or equivalent:
Expand Down Expand Up @@ -131,11 +131,11 @@ sudo pacman -R flutter # for Arch
choco install fvm
```

3. Install and use Flutter 3.35.2:
3. Install and use Flutter 3.35.3:

```powershell
fvm install 3.35.2
fvm global 3.35.2
fvm install 3.35.3
fvm global 3.35.3
```

4. Add FVM's Flutter version to your PATH:
Expand All @@ -158,7 +158,7 @@ To use a specific Flutter version for a project:
2. Run:

```bash
fvm use 3.35.2
fvm use 3.35.3
```

This will create a `.fvmrc` file in your project, which specifies the Flutter version to use for this project.
Expand Down
57 changes: 37 additions & 20 deletions lib/bloc/auth_bloc/auth_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
final WalletsRepository _walletsRepository;
final SettingsRepository _settingsRepository;
StreamSubscription<KdfUser?>? _authChangesSubscription;
@override
final _log = Logger('AuthBloc');

@override
Expand Down Expand Up @@ -91,11 +92,10 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
);
}

_log.info('login from a wallet');
emit(AuthBlocState.loading());

_log.info('Logging in to an existing wallet.');
final weakPasswordsAllowed = await _areWeakPasswordsAllowed();

await _kdfSdk.auth.signIn(
walletName: event.wallet.name,
password: event.password,
Expand All @@ -111,7 +111,7 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
return emit(AuthBlocState.error(AuthException.notSignedIn()));
}

_log.info('logged in from a wallet');
_log.info('Successfully logged in to wallet');
emit(AuthBlocState.loggedIn(currentUser));
_listenToAuthStateChanges();
} catch (e, s) {
Expand Down Expand Up @@ -159,13 +159,17 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
try {
emit(AuthBlocState.loading());
if (await _didSignInExistingWallet(event.wallet, event.password)) {
add(
AuthSignInRequested(wallet: event.wallet, password: event.password),
);
_log.warning(
'Wallet ${event.wallet.name} already exists, attempting sign-in',
);
return;
}

_log.info('register from a wallet');

_log.info('Registering a new wallet');
final weakPasswordsAllowed = await _areWeakPasswordsAllowed();

await _kdfSdk.auth.register(
password: event.password,
walletName: event.wallet.name,
Expand All @@ -177,7 +181,9 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
),
);

_log.info('registered from a wallet');
_log.info(
'Registered a new wallet, setting up metadata and logging in...',
);
await _kdfSdk.setWalletType(event.wallet.config.type);
await _kdfSdk.confirmSeedBackup(hasBackup: false);
await _kdfSdk.addActivatedCoins(enabledByDefaultCoins);
Expand Down Expand Up @@ -205,15 +211,19 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
Emitter<AuthBlocState> emit,
) async {
try {
emit(AuthBlocState.loading());
if (await _didSignInExistingWallet(event.wallet, event.password)) {
add(
AuthSignInRequested(wallet: event.wallet, password: event.password),
);
_log.warning(
'Wallet ${event.wallet.name} already exists, attempting sign-in',
);
return;
}

_log.info('restore from a wallet');

emit(AuthBlocState.loading());
_log.info('Restoring wallet from a seed');
final weakPasswordsAllowed = await _areWeakPasswordsAllowed();

await _kdfSdk.auth.register(
password: event.password,
walletName: event.wallet.name,
Expand All @@ -226,27 +236,36 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
),
);

_log.info('restored from a wallet');
_log.info(
'Successfully restored wallet from a seed. '
'Setting up wallet metadata and logging in...',
);
await _kdfSdk.setWalletType(event.wallet.config.type);
await _kdfSdk.confirmSeedBackup(hasBackup: event.wallet.config.hasBackup);
await _kdfSdk.addActivatedCoins(enabledByDefaultCoins);

final currentUser = await _kdfSdk.auth.currentUser;
if (currentUser == null) {
throw Exception('Registration failed: user is not signed in');
if (event.wallet.config.activatedCoins.isNotEmpty) {
await _kdfSdk.addActivatedCoins(event.wallet.config.activatedCoins);
Comment thread
takenagain marked this conversation as resolved.
}
emit(AuthBlocState.loggedIn(currentUser));

// Delete legacy wallet on successful restoration & login to avoid
// duplicates in the wallet list
if (event.wallet.isLegacyWallet) {
await _kdfSdk.addActivatedCoins(event.wallet.config.activatedCoins);
_log.info(
'Migration successful. '
'Deleting legacy wallet ${event.wallet.name}',
);
await _walletsRepository.deleteWallet(
event.wallet,
password: event.password,
);
}

final currentUser = await _kdfSdk.auth.currentUser;
if (currentUser == null) {
throw Exception('Restoration from seed failed: user is not signed in');
}

emit(AuthBlocState.loggedIn(currentUser));
_listenToAuthStateChanges();
} catch (e, s) {
final errorMsg = 'Failed to restore existing wallet ${event.wallet.name}';
Expand All @@ -266,8 +285,6 @@ class AuthBloc extends Bloc<AuthBlocEvent, AuthBlocState> with TrezorAuthMixin {
(KdfUser user) => user.walletId.name == wallet.name,
);
if (walletExists) {
add(AuthSignInRequested(wallet: wallet, password: password));
_log.warning('Wallet ${wallet.name} already exist, attempting sign-in');
return true;
}

Expand Down
63 changes: 37 additions & 26 deletions lib/blocs/wallets_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class WalletsRepository {
this._legacyWalletStorage, {
EncryptionTool? encryptionTool,
FileLoader? fileLoader,
}) : _encryptionTool = encryptionTool ?? EncryptionTool(),
_fileLoader = fileLoader ?? FileLoader.fromPlatform();
}) : _encryptionTool = encryptionTool ?? EncryptionTool(),
_fileLoader = fileLoader ?? FileLoader.fromPlatform();

final KomodoDefiSdk _kdfSdk;
final Mm2Api _mm2Api;
Expand All @@ -34,9 +34,10 @@ class WalletsRepository {

Future<List<Wallet>> getWallets() async {
final legacyWallets = await _getLegacyWallets();
final sdkWallets = await _kdfSdk.wallets;

// TODO: move wallet filtering logic to the SDK
_cachedWallets = (await _kdfSdk.wallets)
_cachedWallets = sdkWallets
.where(
(wallet) =>
wallet.config.type != WalletType.trezor &&
Expand All @@ -47,21 +48,26 @@ class WalletsRepository {
}

Future<List<Wallet>> _getLegacyWallets() async {
final newVariable =
await _legacyWalletStorage.read(allWalletsStorageKey) as List?;
final List<Map<String, dynamic>> json =
newVariable?.cast<Map<String, dynamic>>() ?? <Map<String, dynamic>>[];

return json
.map((Map<String, dynamic> w) =>
Wallet.fromJson(w)..config.isLegacyWallet = true)
.toList();
final rawLegacyWallets =
(await _legacyWalletStorage.read(allWalletsStorageKey) as List?)
?.cast<Map<String, dynamic>>() ??
[];

return rawLegacyWallets.map((Map<String, dynamic> w) {
final wallet = Wallet.fromJson(w);
return wallet.copyWith(
config: wallet.config.copyWith(
// Wallet type for legacy wallets is iguana, to avoid confusion with
// missing/empty balances. Sign into iguana for legacy wallets by
// default, but allow for them to be signed into hdwallet if desired.
type: WalletType.iguana,
isLegacyWallet: true,
),
);
}).toList();
}

Future<void> deleteWallet(
Wallet wallet, {
required String password,
}) async {
Future<void> deleteWallet(Wallet wallet, {required String password}) async {
log(
'Deleting a wallet ${wallet.id}',
path: 'wallet_bloc => deleteWallet',
Expand All @@ -82,9 +88,11 @@ class WalletsRepository {
_cachedWallets?.removeWhere((w) => w.name == wallet.name);
return;
} catch (e) {
log('Failed to delete wallet: $e',
path: 'wallet_bloc => deleteWallet', isError: true)
.ignore();
log(
'Failed to delete wallet: $e',
path: 'wallet_bloc => deleteWallet',
isError: true,
).ignore();
rethrow;
}
}
Expand All @@ -99,14 +107,14 @@ class WalletsRepository {
getWallets().ignore();
return null;
}

final trimmedName = name.trim();

// Check if the trimmed name is empty (prevents space-only names)
if (trimmedName.isEmpty) {
return LocaleKeys.walletCreationNameLengthError.tr();
}

// Check if trimmed name exceeds length limit
if (trimmedName.length > 40) {
return LocaleKeys.walletCreationNameLengthError.tr();
Expand All @@ -122,8 +130,9 @@ class WalletsRepository {
}

Future<void> resetSpecificWallet(Wallet wallet) async {
final coinsToDeactivate = wallet.config.activatedCoins
.where((coin) => !enabledByDefaultCoins.contains(coin));
final coinsToDeactivate = wallet.config.activatedCoins.where(
(coin) => !enabledByDefaultCoins.contains(coin),
);
for (final coin in coinsToDeactivate) {
await _mm2Api.disableCoin(coin);
}
Expand All @@ -140,8 +149,10 @@ class WalletsRepository {
);
}
final String data = jsonEncode(wallet.config);
final String encryptedData =
await _encryptionTool.encryptData(password, data);
final String encryptedData = await _encryptionTool.encryptData(
password,
data,
);
final String sanitizedFileName = _sanitizeFileName(wallet.name);
await _fileLoader.save(
fileName: sanitizedFileName,
Expand Down
Loading
Loading