Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class _CreateAccountScreenState extends ConsumerState<CreateAccountScreen> {
_isLoading = true;
});
try {
final account = await _accountsService.createNewAccount();
final account = await _accountsService.createNewAccount(walletIndex: 0);
final checkphrase = await _checksumService.getHumanReadableName(account.accountId);

if (mounted) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,16 @@ class CreateWalletAndBackupScreenState extends ConsumerState<CreateWalletAndBack
setState(() {
_isSubmitting = true;
});

final walletIndex = 0;
try {
await _settingsService.setMnemonic(_mnemonic);
await _settingsService.setMnemonic(_mnemonic, walletIndex);

final asyncAccounts = ref.read(accountsProvider); // Gets notifier state
final accounts = asyncAccounts.value ?? <Account>[]; // Extract data or empty list
if (accounts.isEmpty) {
await _accountsService.addAccount(Account(index: 0, name: _accountName.value.text, accountId: _address));
await _accountsService.addAccount(
Account(walletIndex: walletIndex, index: 0, name: _accountName.value.text, accountId: _address),
);
await _referralService.submitAddressToBackend();
}
ref.invalidate(accountsProvider);
Expand Down
10 changes: 6 additions & 4 deletions mobile-app/lib/features/main/screens/import_wallet_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ImportWalletScreenState extends ConsumerState<ImportWalletScreen> {
}
}

Future<void> _importWallet() async {
Future<void> _importWallet({required int walletIndex}) async {
setState(() {
_isLoading = true;
_errorMessage = '';
Expand All @@ -81,8 +81,10 @@ class ImportWalletScreenState extends ConsumerState<ImportWalletScreen> {
}

final key = HdWalletService().keyPairAtIndex(mnemonic, 0);
await _settingsService.setMnemonic(mnemonic);
await _accountsService.addAccount(Account(index: 0, name: 'Account 1', accountId: key.ss58Address));
await _settingsService.setMnemonic(mnemonic, walletIndex);
await _accountsService.addAccount(
Account(walletIndex: walletIndex, index: 0, name: 'Account 1', accountId: key.ss58Address),
);

await _discoverAccounts(mnemonic);
// We set check status to true so we will not prompt user to input refferal code.
Expand Down Expand Up @@ -190,7 +192,7 @@ class ImportWalletScreenState extends ConsumerState<ImportWalletScreen> {
Button(
variant: ButtonVariant.primary,
label: 'Import Wallet',
onPressed: _importWallet,
onPressed: () => _importWallet(walletIndex: 0),
isLoading: _isLoading,
),
SizedBox(height: context.themeSize.bottomButtonSpacing),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import 'package:resonance_network_wallet/shared/extensions/clipboard_extensions.
import 'package:resonance_network_wallet/shared/extensions/media_query_data_extension.dart';

class ShowRecoveryPhraseScreen extends StatefulWidget {
const ShowRecoveryPhraseScreen({super.key});
const ShowRecoveryPhraseScreen({super.key, this.walletIndex = 0});

final int walletIndex;

@override
State<ShowRecoveryPhraseScreen> createState() => _ShowRecoveryPhraseScreenState();
Expand All @@ -30,7 +32,7 @@ class _ShowRecoveryPhraseScreenState extends State<ShowRecoveryPhraseScreen> {
}

Future<void> _loadMnemonic() async {
final mnemonic = await _settingsService.getMnemonic();
final mnemonic = await _settingsService.getMnemonic(widget.walletIndex);
if (mnemonic != null) {
setState(() {
_recoveryPhrase = mnemonic.split(' ');
Expand Down
2 changes: 1 addition & 1 deletion mobile-app/test/widget/send_screen_widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void main() {

// --- 1. Settings Service Stubs ---
when(mockSettingsService.getActiveAccount()).thenAnswer((_) async {
return const Account(index: 0, name: 'Test User', accountId: 'test_account_id');
return const Account(walletIndex: 0, index: 0, name: 'Test User', accountId: 'test_account_id');
});
when(mockSettingsService.getReversibleTimeSeconds()).thenAnswer((_) async => 600);

Expand Down
4 changes: 2 additions & 2 deletions mobile-app/test/widget/send_screen_widget_test.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class MockSettingsService extends _i1.Mock implements _i2.SettingsService {
as _i3.Future<bool>);

@override
_i3.Future<void> setMnemonic(String? mnemonic) =>
_i3.Future<void> setMnemonic(String? mnemonic, int? mnemonicIndex) =>
(super.noSuchMethod(
Invocation.method(#setMnemonic, [mnemonic]),
returnValue: _i3.Future<void>.value(),
Expand All @@ -178,7 +178,7 @@ class MockSettingsService extends _i1.Mock implements _i2.SettingsService {
as _i3.Future<void>);

@override
_i3.Future<String?> getMnemonic() =>
_i3.Future<String?> getMnemonic(int? mnemonicIndex) =>
(super.noSuchMethod(Invocation.method(#getMnemonic, []), returnValue: _i3.Future<String?>.value())
as _i3.Future<String?>);

Expand Down
1 change: 0 additions & 1 deletion quantus_sdk/lib/src/constants/app_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class AppConstants {

// Shared Preferences keys
static const String hasWalletKey = 'has_wallet';
static const String mnemonicKey = 'mnemonic';
static const String accountIdKey = 'account_id';

// Reversible time settings
Expand Down
2 changes: 1 addition & 1 deletion quantus_sdk/lib/src/extensions/account_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ extension HDWalletAccount on Account {
}

Future<String?> getMnemonic() async {
return SettingsService().getMnemonic();
return SettingsService().getMnemonic(walletIndex);
}
}
37 changes: 32 additions & 5 deletions quantus_sdk/lib/src/models/account.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,48 @@
import 'package:flutter/foundation.dart';

enum AccountType { local, keystone }

@immutable
class Account {
final int walletIndex;
final int index; // derivation index
final String name;
final String accountId; // address
const Account({required this.index, required this.name, required this.accountId});
final AccountType accountType;
const Account({
required this.walletIndex,
required this.index,
required this.name,
required this.accountId,
this.accountType = AccountType.local,
});

factory Account.fromJson(Map<String, dynamic> json) {
return Account(index: json['index'] as int, name: json['name'] as String, accountId: json['accountId'] as String);
return Account(
walletIndex: (json['walletIndex'] ?? 0) as int,
index: json['index'] as int,
name: json['name'] as String,
accountId: json['accountId'] as String,
accountType: AccountType.values.byName(json['accountType'] as String? ?? AccountType.local.name),
);
}

Map<String, dynamic> toJson() {
return {'index': index, 'name': name, 'accountId': accountId};
return {
'walletIndex': walletIndex,
'index': index,
'name': name,
'accountId': accountId,
'accountType': accountType.name,
};
}

Account copyWith({int? index, String? name, String? accountId, int? uiPosition}) {
return Account(index: index ?? this.index, name: name ?? this.name, accountId: accountId ?? this.accountId);
Account copyWith({int? walletIndex, int? index, String? name, String? accountId, int? uiPosition}) {
return Account(
walletIndex: walletIndex ?? this.walletIndex,
index: index ?? this.index,
name: name ?? this.name,
accountId: accountId ?? this.accountId,
);
}
}
9 changes: 8 additions & 1 deletion quantus_sdk/lib/src/services/account_discovery_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class AccountDiscoveryService {

// Add raw account
final rawKeyPair = _substrateService.nonHDdilithiumKeypairFromMnemonic(mnemonic);
final baseWalletIndex = 0;
final rawAccount = Account(
walletIndex: baseWalletIndex,
index: -1, // indicator for a raw account
name: 'Primary Account',
accountId: rawKeyPair.ss58Address,
Expand All @@ -31,7 +33,12 @@ class AccountDiscoveryService {
// Add HD accounts
for (var i = 0; i < count; i++) {
final keyPair = _hdWalletService.keyPairAtIndex(mnemonic, i);
final account = Account(index: i, name: 'Account ${i + 1}', accountId: keyPair.ss58Address);
final account = Account(
walletIndex: baseWalletIndex,
index: i,
name: 'Account ${i + 1}',
accountId: keyPair.ss58Address,
);
allPossibleAccounts.add(account);
}

Expand Down
5 changes: 3 additions & 2 deletions quantus_sdk/lib/src/services/accounts_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ class AccountsService {
final SettingsService _settingsService = SettingsService();
void Function()? onAccountsChanged;

Future<Account> createNewAccount() async {
final mnemonic = await _settingsService.getMnemonic();
Future<Account> createNewAccount({required int walletIndex}) async {
final mnemonic = await _settingsService.getMnemonic(walletIndex);
if (mnemonic == null) {
throw Exception('Mnemonic not found. Cannot create new account.');
}
final nextIndex = await _settingsService.getNextFreeAccountIndex();
final keypair = HdWalletService().keyPairAtIndex(mnemonic, nextIndex);
final newAccount = Account(
walletIndex: walletIndex,
index: nextIndex,
name: 'Account ${nextIndex + 1}', // Default name
accountId: keypair.ss58Address,
Expand Down
15 changes: 11 additions & 4 deletions quantus_sdk/lib/src/services/migration_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:quantus_sdk/src/services/settings_service.dart';
class MigrationService {
final SettingsService _settingsService;
final HdWalletService _hdWalletService;
final int baseWalletIndex = 0;

MigrationService(this._settingsService, this._hdWalletService);

Expand All @@ -20,7 +21,7 @@ class MigrationService {
/// Get migration data including old accounts with their public keys
Future<List<MigrationAccountData>> getMigrationData() async {
final oldAccounts = _settingsService.getOldAccounts();
final mnemonic = await _settingsService.getMnemonic();
final mnemonic = await _settingsService.getMnemonic(baseWalletIndex);

if (mnemonic == null) {
throw Exception('No mnemonic found for migration');
Expand Down Expand Up @@ -54,6 +55,7 @@ class MigrationService {
);

final newAccount = Account(
walletIndex: baseWalletIndex,
index: data.oldAccount.index,
name: data.oldAccount.name,
accountId: data.newAccountId,
Expand All @@ -76,9 +78,14 @@ class MigrationService {
/// Debug method to create test old accounts
Future<void> createDebugOldAccounts() async {
final debugAccounts = [
const Account(index: -1, name: 'Primary Account', accountId: 'qznd1YWbgQrviV76psu5n8d24mHSuHtAc9JmJLB42gTELksvQ'),
const Account(index: 0, name: 'Account 0', accountId: 'debug_id_0'),
const Account(index: 1, name: 'Account 1', accountId: 'debug_id_1'),
const Account(
walletIndex: 0,
index: -1,
name: 'Primary Account',
accountId: 'qznd1YWbgQrviV76psu5n8d24mHSuHtAc9JmJLB42gTELksvQ',
),
const Account(walletIndex: 0, index: 0, name: 'Account 0', accountId: 'debug_id_0'),
const Account(walletIndex: 0, index: 1, name: 'Account 1', accountId: 'debug_id_1'),
];

final jsonData = jsonEncode(debugAccounts.map((a) => a.toJson()).toList());
Expand Down
12 changes: 7 additions & 5 deletions quantus_sdk/lib/src/services/settings_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class SettingsService {
final oldAccountId = _prefs.getString('account_id');
if (oldAccountId != null) {
final oldWalletName = _prefs.getString('wallet_name') ?? 'Account 1';
final account = Account(index: 0, name: oldWalletName, accountId: oldAccountId);
final account = Account(walletIndex: 0, index: 0, name: oldWalletName, accountId: oldAccountId);
await saveAccounts([account]);
await setActiveAccount(account);
// Clean up old keys after migration
Expand Down Expand Up @@ -178,13 +178,15 @@ class SettingsService {
return accounts.isEmpty;
}

String getMnemonicKey(int mnemonicIndex) => mnemonicIndex == 0 ? 'mnemonic' : 'mnemonic_$mnemonicIndex';

// Mnemonic Settings - Using secure storage
Future<void> setMnemonic(String mnemonic) async {
await _secureStorage.write(key: 'mnemonic', value: mnemonic);
Future<void> setMnemonic(String mnemonic, int mnemonicIndex) async {
await _secureStorage.write(key: getMnemonicKey(mnemonicIndex), value: mnemonic);
}

Future<String?> getMnemonic() async {
return await _secureStorage.read(key: 'mnemonic');
Future<String?> getMnemonic(int mnemonicIndex) async {
return await _secureStorage.read(key: getMnemonicKey(mnemonicIndex));
}

// Reversible Time Settings
Expand Down
4 changes: 2 additions & 2 deletions quantus_sdk/lib/src/services/taskmaster_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class TaskmasterService {
}

Future<String> getOldMiningAccountId() async {
final mnemonic = await _settingsService.getMnemonic();
final mnemonic = await _settingsService.getMnemonic(0);
if (mnemonic == null) {
throw Exception('Mnemonic not found.');
}
Expand All @@ -174,7 +174,7 @@ class TaskmasterService {
}

Future<TokenInfo> loginWithAccount1() async {
final mnemonic = await _settingsService.getMnemonic();
final mnemonic = await _settingsService.getMnemonic(0);
if (mnemonic == null) {
throw Exception('Mnemonic not found.');
}
Expand Down
6 changes: 3 additions & 3 deletions quantus_sdk/test/services/settings_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ void main() {
late SettingsService settingsService;

// Accounts for testing
const account1 = Account(index: 0, name: 'Account 1', accountId: 'id_1');
const account2 = Account(index: 1, name: 'Account 2', accountId: 'id_2');
const account3 = Account(index: 2, name: 'Account 3', accountId: 'id_3');
const account1 = Account(walletIndex: 0, index: 0, name: 'Account 1', accountId: 'id_1');
const account2 = Account(walletIndex: 0, index: 1, name: 'Account 2', accountId: 'id_2');
const account3 = Account(walletIndex: 0, index: 2, name: 'Account 3', accountId: 'id_3');

setUp(() async {
// Reset mock storage BEFORE any SharedPreferences.getInstance() calls
Expand Down