Skip to content

Commit 628eae3

Browse files
committed
dcr: Always fetch the current dir path.
On ios devices the path will change between updates breaking decred. Never save the path and always check to ensure it is up to date. Previous wallets were also not creating a directory in the correct place. Move those when found.
1 parent dd8413b commit 628eae3

File tree

2 files changed

+85
-38
lines changed

2 files changed

+85
-38
lines changed

cw_decred/lib/wallet.dart

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import 'dart:io';
44
import 'package:cw_core/exceptions.dart';
55
import 'package:cw_core/transaction_direction.dart';
66
import 'package:cw_core/utils/print_verbose.dart';
7+
import 'package:cw_core/pathForWallet.dart';
8+
import 'package:cw_core/wallet_type.dart';
79
import 'package:cw_decred/amount_format.dart';
810
import 'package:cw_decred/pending_transaction.dart';
911
import 'package:cw_decred/transaction_credentials.dart';
@@ -306,9 +308,10 @@ abstract class DecredWalletBase
306308
persistantPeer = addr;
307309
await _libwallet.closeWallet(walletInfo.name);
308310
final network = isTestnet ? "testnet" : "mainnet";
311+
final dirPath = await pathForWalletDir(name: walletInfo.name, type: WalletType.decred);
309312
final config = {
310313
"name": walletInfo.name,
311-
"datadir": walletInfo.dirPath,
314+
"datadir": dirPath,
312315
"net": network,
313316
"unsyncedaddrs": true,
314317
};
@@ -593,17 +596,7 @@ abstract class DecredWalletBase
593596
@override
594597
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => onError;
595598

596-
Future<void> renameWalletFiles(String newWalletName) async {
597-
final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type);
598-
599-
final newDirPath = await pathForWalletDir(name: newWalletName, type: type);
600-
601-
if (File(newDirPath).existsSync()) {
602-
throw "wallet already exists at $newDirPath";
603-
}
604-
605-
await Directory(currentDirPath).rename(newDirPath);
606-
}
599+
Future<void> renameWalletFiles(String newWalletName) async {}
607600

608601
@override
609602
Future<String> signMessage(String message, {String? address = null}) async {

cw_decred/lib/wallet_service.dart

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:cw_core/wallet_service.dart';
88
import 'package:cw_core/pathForWallet.dart';
99
import 'package:cw_core/wallet_info.dart';
1010
import 'package:cw_core/wallet_type.dart';
11+
import 'package:path/path.dart';
1112
import 'package:hive/hive.dart';
1213
import 'package:collection/collection.dart';
1314
import 'package:cw_core/unspent_coins_info.dart';
@@ -57,42 +58,90 @@ class DecredWalletService extends WalletService<
5758
@override
5859
Future<DecredWallet> create(DecredNewWalletCredentials credentials, {bool? isTestnet}) async {
5960
await this.init();
61+
final dirPath = await pathForWalletDir(name: credentials.walletInfo!.name, type: getType());
62+
final network = isTestnet == true ? testnet : mainnet;
6063
final config = {
6164
"name": credentials.walletInfo!.name,
62-
"datadir": credentials.walletInfo!.dirPath,
65+
"datadir": dirPath,
6366
"pass": credentials.password!,
64-
"net": isTestnet == true ? testnet : mainnet,
67+
"net": network,
6568
"unsyncedaddrs": true,
6669
};
6770
await libwallet!.createWallet(jsonEncode(config));
6871
final di = DerivationInfo(
6972
derivationPath: isTestnet == true ? seedRestorePathTestnet : seedRestorePath);
7073
credentials.walletInfo!.derivationInfo = di;
74+
credentials.walletInfo!.network = network;
75+
// ios will move our wallet directory when updating. Since we must
76+
// recalculate the new path every time we open the wallet, ensure this path
77+
// is not used. An older wallet will have a directory here which is a
78+
// condition for moving the wallet when opening, so this must be kept blank
79+
// going forward.
80+
credentials.walletInfo!.dirPath = "";
81+
credentials.walletInfo!.path = "";
7182
final wallet = DecredWallet(credentials.walletInfo!, credentials.password!,
7283
this.unspentCoinsInfoSource, libwallet!, closeLibwallet);
7384
await wallet.init();
7485
return wallet;
7586
}
7687

88+
void copyDirectorySync(Directory source, Directory destination) {
89+
/// create destination folder if not exist
90+
if (!destination.existsSync()) {
91+
destination.createSync(recursive: true);
92+
}
93+
94+
/// get all files from source (recursive: false is important here)
95+
source.listSync(recursive: false).forEach((entity) {
96+
final newPath = destination.path + Platform.pathSeparator + basename(entity.path);
97+
if (entity is File) {
98+
entity.copySync(newPath);
99+
} else if (entity is Directory) {
100+
copyDirectorySync(entity, Directory(newPath));
101+
}
102+
});
103+
}
104+
105+
Future<void> moveWallet(String fromPath, String toPath) async {
106+
final oldWalletDir = new Directory(fromPath);
107+
final newWalletDir = new Directory(toPath);
108+
copyDirectorySync(oldWalletDir, newWalletDir);
109+
await oldWalletDir.delete(recursive: true);
110+
}
111+
77112
@override
78113
Future<DecredWallet> openWallet(String name, String password) async {
79114
final walletInfo = walletInfoSource.values
80115
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
81-
final network = walletInfo.derivationInfo?.derivationPath == seedRestorePathTestnet ||
82-
walletInfo.derivationInfo?.derivationPath == pubkeyRestorePathTestnet
83-
? testnet
84-
: mainnet;
85116

86117
await this.init();
87-
final walletDirExists = Directory(walletInfo.dirPath).existsSync();
88-
if (!walletDirExists) {
89-
walletInfo.dirPath = await pathForWalletDir(name: name, type: getType());
118+
119+
// Cake wallet version 4.27.0 and earlier gave a wallet dir that did not
120+
// match the name. Move those to the correct place.
121+
final dirPath = await pathForWalletDir(name: name, type: getType());
122+
if (walletInfo.dirPath != "") {
123+
// On ios the stored dir no longer exists. We can only trust the basename.
124+
final randomBasename = basename(walletInfo.dirPath);
125+
final oldDir = await pathForWalletDir(name: randomBasename, type: getType());
126+
if (oldDir != dirPath) {
127+
this.moveWallet(oldDir, dirPath);
128+
}
129+
// Clear the path so this does not trigger again.
130+
walletInfo.dirPath = "";
131+
walletInfo.path = "";
132+
}
133+
134+
if (walletInfo.network == null || walletInfo.network == "") {
135+
walletInfo.network = walletInfo.derivationInfo?.derivationPath == seedRestorePathTestnet ||
136+
walletInfo.derivationInfo?.derivationPath == pubkeyRestorePathTestnet
137+
? testnet
138+
: mainnet;
90139
}
91140

92141
final config = {
93-
"name": walletInfo.name,
94-
"datadir": walletInfo.dirPath,
95-
"net": network,
142+
"name": name,
143+
"datadir": dirPath,
144+
"net": walletInfo.network,
96145
"unsyncedaddrs": true,
97146
};
98147
await libwallet!.loadWallet(jsonEncode(config));
@@ -114,21 +163,16 @@ class DecredWalletService extends WalletService<
114163
Future<void> rename(String currentName, String password, String newName) async {
115164
final currentWalletInfo = walletInfoSource.values
116165
.firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
117-
final network = currentWalletInfo.derivationInfo?.derivationPath == seedRestorePathTestnet ||
118-
currentWalletInfo.derivationInfo?.derivationPath == pubkeyRestorePathTestnet
119-
? testnet
120-
: mainnet;
121-
final currentWallet = DecredWallet(
122-
currentWalletInfo, password, this.unspentCoinsInfoSource, libwallet!, closeLibwallet);
123-
124-
await currentWallet.renameWalletFiles(newName);
125166

167+
final currentDirPath = await pathForWalletDir(name: currentName, type: getType());
126168
final newDirPath = await pathForWalletDir(name: newName, type: getType());
169+
this.moveWallet(currentDirPath, newDirPath);
170+
127171
final newWalletInfo = currentWalletInfo;
128172
newWalletInfo.id = WalletBase.idFor(newName, getType());
129173
newWalletInfo.name = newName;
130-
newWalletInfo.dirPath = newDirPath;
131-
newWalletInfo.network = network;
174+
newWalletInfo.dirPath = "";
175+
newWalletInfo.path = "";
132176

133177
await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
134178
}
@@ -137,18 +181,23 @@ class DecredWalletService extends WalletService<
137181
Future<DecredWallet> restoreFromSeed(DecredRestoreWalletFromSeedCredentials credentials,
138182
{bool? isTestnet}) async {
139183
await this.init();
184+
final network = isTestnet == true ? testnet : mainnet;
185+
final dirPath = await pathForWalletDir(name: credentials.walletInfo!.name, type: getType());
140186
final config = {
141187
"name": credentials.walletInfo!.name,
142-
"datadir": credentials.walletInfo!.dirPath,
188+
"datadir": dirPath,
143189
"pass": credentials.password!,
144190
"mnemonic": credentials.mnemonic,
145-
"net": isTestnet == true ? testnet : mainnet,
191+
"net": network,
146192
"unsyncedaddrs": true,
147193
};
148194
await libwallet!.createWallet(jsonEncode(config));
149195
final di = DerivationInfo(
150196
derivationPath: isTestnet == true ? seedRestorePathTestnet : seedRestorePath);
151197
credentials.walletInfo!.derivationInfo = di;
198+
credentials.walletInfo!.network = network;
199+
credentials.walletInfo!.dirPath = "";
200+
credentials.walletInfo!.path = "";
152201
final wallet = DecredWallet(credentials.walletInfo!, credentials.password!,
153202
this.unspentCoinsInfoSource, libwallet!, closeLibwallet);
154203
await wallet.init();
@@ -161,17 +210,22 @@ class DecredWalletService extends WalletService<
161210
Future<DecredWallet> restoreFromKeys(DecredRestoreWalletFromPubkeyCredentials credentials,
162211
{bool? isTestnet}) async {
163212
await this.init();
213+
final network = isTestnet == true ? testnet : mainnet;
214+
final dirPath = await pathForWalletDir(name: credentials.walletInfo!.name, type: getType());
164215
final config = {
165216
"name": credentials.walletInfo!.name,
166-
"datadir": credentials.walletInfo!.dirPath,
217+
"datadir": dirPath,
167218
"pubkey": credentials.pubkey,
168-
"net": isTestnet == true ? testnet : mainnet,
219+
"net": network,
169220
"unsyncedaddrs": true,
170221
};
171222
await libwallet!.createWatchOnlyWallet(jsonEncode(config));
172223
final di = DerivationInfo(
173224
derivationPath: isTestnet == true ? pubkeyRestorePathTestnet : pubkeyRestorePath);
174225
credentials.walletInfo!.derivationInfo = di;
226+
credentials.walletInfo!.network = network;
227+
credentials.walletInfo!.dirPath = "";
228+
credentials.walletInfo!.path = "";
175229
final wallet = DecredWallet(credentials.walletInfo!, credentials.password!,
176230
this.unspentCoinsInfoSource, libwallet!, closeLibwallet);
177231
await wallet.init();

0 commit comments

Comments
 (0)