Skip to content

Commit 3ccfa58

Browse files
committed
feat: initial hive -> SQLite
Includes migration script and initial work done to remove dependency on hive generators. Also contains some refactoring to make sync code async. Aspects that need testing: - backups - wallet loading / wallet list - almost everything else - renaming - deletion - sorting in wallet list
1 parent 4aac641 commit 3ccfa58

File tree

103 files changed

+2409
-813
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+2409
-813
lines changed

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ RUN set -o xtrace \
5757
bridge-utils libvirt-clients libvirt-daemon-system qemu-kvm udev \
5858
# Linux test dependencies
5959
ffmpeg network-manager x11-utils xvfb psmisc \
60+
# database
61+
libsqlite3-0 libsqlite3-dev \
6062
# aarch64-linux-gnu dependencies
6163
g++-aarch64-linux-gnu gcc-aarch64-linux-gnu \
6264
# x86_64-linux-gnu dependencies

cw_bitcoin/lib/bitcoin_wallet.dart

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
4646
BitcoinWalletBase({
4747
required String password,
4848
required WalletInfo walletInfo,
49+
required DerivationInfo derivationInfo,
4950
required Box<UnspentCoinsInfo> unspentCoinsInfo,
5051
required Box<PayjoinSession> payjoinBox,
5152
required EncryptionFileUtils encryptionFileUtils,
@@ -68,6 +69,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
6869
xpub: xpub,
6970
password: password,
7071
walletInfo: walletInfo,
72+
derivationInfo: derivationInfo,
7173
unspentCoinsInfo: unspentCoinsInfo,
7274
network: networkParam == null
7375
? BitcoinNetwork.mainnet
@@ -132,7 +134,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
132134
}) async {
133135
late Uint8List seedBytes;
134136

135-
switch (walletInfo.derivationInfo?.derivationType) {
137+
final derivationInfo = await walletInfo.getDerivationInfo();
138+
139+
switch (derivationInfo.derivationType) {
136140
case DerivationType.bip39:
137141
seedBytes = await bip39.mnemonicToSeed(
138142
mnemonic,
@@ -151,6 +155,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
151155
passphrase: passphrase ?? "",
152156
password: password,
153157
walletInfo: walletInfo,
158+
derivationInfo: derivationInfo,
154159
unspentCoinsInfo: unspentCoinsInfo,
155160
initialAddresses: initialAddresses,
156161
initialSilentAddresses: initialSilentAddresses,
@@ -211,20 +216,20 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
211216
);
212217
}
213218

214-
walletInfo.derivationInfo ??= DerivationInfo();
219+
final derivationInfo = await walletInfo.getDerivationInfo();
215220

216221
// set the default if not present:
217-
walletInfo.derivationInfo!.derivationPath ??=
222+
derivationInfo.derivationPath ??=
218223
snp?.derivationPath ?? electrum_path;
219-
walletInfo.derivationInfo!.derivationType ??=
224+
derivationInfo.derivationType ??=
220225
snp?.derivationType ?? DerivationType.electrum;
221226

222227
Uint8List? seedBytes = null;
223228
final mnemonic = keysData.mnemonic;
224229
final passphrase = keysData.passphrase;
225230

226231
if (mnemonic != null) {
227-
switch (walletInfo.derivationInfo!.derivationType) {
232+
switch (derivationInfo.derivationType) {
228233
case DerivationType.electrum:
229234
seedBytes =
230235
await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
@@ -245,6 +250,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
245250
password: password,
246251
passphrase: passphrase,
247252
walletInfo: walletInfo,
253+
derivationInfo: derivationInfo,
248254
unspentCoinsInfo: unspentCoinsInfo,
249255
initialAddresses: snp?.addresses,
250256
initialSilentAddresses: snp?.silentAddresses,
@@ -264,10 +270,11 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
264270
BitcoinLedgerApp? _bitcoinLedgerApp;
265271

266272
@override
267-
void setLedgerConnection(LedgerConnection connection) {
273+
Future<void> setLedgerConnection(LedgerConnection connection) async {
268274
_ledgerConnection = connection;
275+
final derivationInfo = await walletInfo.getDerivationInfo();
269276
_bitcoinLedgerApp = BitcoinLedgerApp(_ledgerConnection!,
270-
derivationPath: walletInfo.derivationInfo!.derivationPath!);
277+
derivationPath: derivationInfo.derivationPath!);
271278
}
272279

273280
@override
@@ -491,7 +498,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
491498
: null;
492499
final index = addressEntry?.index ?? 0;
493500
final isChange = addressEntry?.isHidden == true ? 1 : 0;
494-
final accountPath = walletInfo.derivationInfo?.derivationPath;
501+
final derivationInfo = await walletInfo.getDerivationInfo();
502+
final accountPath = derivationInfo.derivationPath;
495503
final derivationPath =
496504
accountPath != null ? "$accountPath/$isChange/$index" : null;
497505

cw_bitcoin/lib/bitcoin_wallet_service.dart

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ class BitcoinWalletService extends WalletService<
2222
BitcoinRestoreWalletFromSeedCredentials,
2323
BitcoinWalletFromKeysCredentials,
2424
BitcoinRestoreWalletFromHardware> {
25-
BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource,
25+
BitcoinWalletService(this.unspentCoinsInfoSource,
2626
this.payjoinSessionSource, this.isDirect);
2727

28-
final Box<WalletInfo> walletInfoSource;
2928
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
3029
final Box<PayjoinSession> payjoinSessionSource;
3130
final bool isDirect;
@@ -39,7 +38,8 @@ class BitcoinWalletService extends WalletService<
3938
credentials.walletInfo?.network = network.value;
4039

4140
final String mnemonic;
42-
switch ( credentials.walletInfo?.derivationInfo?.derivationType) {
41+
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
42+
switch (derivationInfo.derivationType) {
4343
case DerivationType.bip39:
4444
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
4545

@@ -50,6 +50,7 @@ class BitcoinWalletService extends WalletService<
5050
mnemonic = await generateElectrumMnemonic();
5151
break;
5252
}
53+
await derivationInfo.save();
5354

5455
final wallet = await BitcoinWalletBase.create(
5556
mnemonic: mnemonic,
@@ -74,8 +75,10 @@ class BitcoinWalletService extends WalletService<
7475

7576
@override
7677
Future<BitcoinWallet> openWallet(String name, String password) async {
77-
final walletInfo = walletInfoSource.values
78-
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
78+
final walletInfo = await WalletInfo.get(name, getType());
79+
if (walletInfo == null) {
80+
throw Exception('Wallet not found');
81+
}
7982
try {
8083
final wallet = await BitcoinWalletBase.open(
8184
password: password,
@@ -106,9 +109,11 @@ class BitcoinWalletService extends WalletService<
106109
@override
107110
Future<void> remove(String wallet) async {
108111
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
109-
final walletInfo = walletInfoSource.values
110-
.firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
111-
await walletInfoSource.delete(walletInfo.key);
112+
final walletInfo = await WalletInfo.get(wallet, getType());
113+
if (walletInfo == null) {
114+
throw Exception('Wallet not found');
115+
}
116+
await WalletInfo.delete(walletInfo);
112117

113118
final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
114119
(unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
@@ -122,8 +127,10 @@ class BitcoinWalletService extends WalletService<
122127

123128
@override
124129
Future<void> rename(String currentName, String password, String newName) async {
125-
final currentWalletInfo = walletInfoSource.values
126-
.firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
130+
final currentWalletInfo = await WalletInfo.get(currentName, getType());
131+
if (currentWalletInfo == null) {
132+
throw Exception('Wallet not found');
133+
}
127134
final currentWallet = await BitcoinWalletBase.open(
128135
password: password,
129136
name: currentName,
@@ -140,20 +147,24 @@ class BitcoinWalletService extends WalletService<
140147
newWalletInfo.id = WalletBase.idFor(newName, getType());
141148
newWalletInfo.name = newName;
142149

143-
await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
150+
await newWalletInfo.save();
144151
}
145152

146153
@override
147154
Future<BitcoinWallet> restoreFromHardwareWallet(BitcoinRestoreWalletFromHardware credentials,
148155
{bool? isTestnet}) async {
149156
final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
150157
credentials.walletInfo?.network = network.value;
151-
credentials.walletInfo?.derivationInfo?.derivationPath =
158+
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
159+
derivationInfo.derivationPath =
152160
credentials.hwAccountData.derivationPath;
161+
await derivationInfo.save();
162+
credentials.walletInfo!.save();
153163
final wallet = await BitcoinWallet(
154164
password: credentials.password!,
155165
xpub: credentials.hwAccountData.xpub,
156166
walletInfo: credentials.walletInfo!,
167+
derivationInfo: derivationInfo,
157168
unspentCoinsInfo: unspentCoinsInfoSource,
158169
networkParam: network,
159170
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
@@ -174,6 +185,7 @@ class BitcoinWalletService extends WalletService<
174185
password: credentials.password!,
175186
xpub: credentials.xpub,
176187
walletInfo: credentials.walletInfo!,
188+
derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
177189
unspentCoinsInfo: unspentCoinsInfoSource,
178190
networkParam: network,
179191
encryptionFileUtils: encryptionFileUtilsFor(isDirect),

cw_bitcoin/lib/electrum_wallet.dart

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ abstract class ElectrumWalletBase
6363
ElectrumWalletBase({
6464
required String password,
6565
required WalletInfo walletInfo,
66+
required DerivationInfo derivationInfo,
6667
required Box<UnspentCoinsInfo> unspentCoinsInfo,
6768
required this.network,
6869
required this.encryptionFileUtils,
@@ -76,7 +77,7 @@ abstract class ElectrumWalletBase
7677
CryptoCurrency? currency,
7778
bool? alwaysScan,
7879
}) : accountHD =
79-
getAccountHDWallet(currency, network, seedBytes, xpub, walletInfo.derivationInfo),
80+
getAccountHDWallet(currency, network, seedBytes, xpub, derivationInfo),
8081
syncStatus = NotConnectedSyncStatus(),
8182
_password = password,
8283
_feeRates = <int>[],
@@ -99,9 +100,10 @@ abstract class ElectrumWalletBase
99100
this.unspentCoinsInfo = unspentCoinsInfo,
100101
this.isTestnet = !network.isMainnet,
101102
this._mnemonic = mnemonic,
102-
super(walletInfo) {
103+
super(walletInfo, derivationInfo) {
103104
this.electrumClient = electrumClient ?? electrum.ElectrumClient();
104105
this.walletInfo = walletInfo;
106+
this.derivationInfo = derivationInfo;
105107
transactionHistory = ElectrumTransactionHistory(
106108
walletInfo: walletInfo,
107109
password: password,
@@ -759,8 +761,9 @@ abstract class ElectrumWalletBase
759761
pubKeyHex = hd.childKey(Bip32KeyIndex(utx.bitcoinAddressRecord.index)).publicKey.toHex();
760762
}
761763

764+
762765
final derivationPath =
763-
"${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? electrum_path)}"
766+
"${_hardenedDerivationPath(derivationInfo?.derivationPath ?? electrum_path)}"
764767
"/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}"
765768
"/${utx.bitcoinAddressRecord.index}";
766769
publicKeys[address.pubKeyHash()] = PublicKeyWithDerivationPath(pubKeyHex, derivationPath);
@@ -969,7 +972,7 @@ abstract class ElectrumWalletBase
969972

970973
// Get Derivation path for change Address since it is needed in Litecoin and BitcoinCash hardware Wallets
971974
final changeDerivationPath =
972-
"${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}"
975+
"${_hardenedDerivationPath(derivationInfo.derivationPath ?? "m/0'")}"
973976
"/${changeAddress.isHidden ? "1" : "0"}"
974977
"/${changeAddress.index}";
975978
utxoDetails.publicKeys[address.pubKeyHash()] =
@@ -1408,7 +1411,7 @@ abstract class ElectrumWalletBase
14081411
}
14091412
}
14101413

1411-
void setLedgerConnection(ledger.LedgerConnection connection) => throw UnimplementedError();
1414+
Future<void> setLedgerConnection(ledger.LedgerConnection connection) => throw UnimplementedError();
14121415

14131416
Future<BtcTransaction> buildHardwareWalletTransaction({
14141417
required List<BitcoinBaseOutput> outputs,
@@ -1435,8 +1438,8 @@ abstract class ElectrumWalletBase
14351438
? SegwitAddresType.p2wpkh.toString()
14361439
: walletInfo.addressPageType.toString(),
14371440
'balance': balance[currency]?.toJSON(),
1438-
'derivationTypeIndex': walletInfo.derivationInfo?.derivationType?.index,
1439-
'derivationPath': walletInfo.derivationInfo?.derivationPath,
1441+
'derivationTypeIndex': derivationInfo.derivationType?.index,
1442+
'derivationPath': derivationInfo.derivationPath,
14401443
'silent_addresses': walletAddresses.silentAddresses.map((addr) => addr.toJSON()).toList(),
14411444
'silent_address_index': walletAddresses.currentSilentAddressIndex.toString(),
14421445
'mweb_addresses': walletAddresses.mwebAddresses.map((addr) => addr.toJSON()).toList(),

cw_bitcoin/lib/litecoin_wallet.dart

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
6060
LitecoinWalletBase({
6161
required String password,
6262
required WalletInfo walletInfo,
63+
required DerivationInfo derivationInfo,
6364
required Box<UnspentCoinsInfo> unspentCoinsInfo,
6465
required EncryptionFileUtils encryptionFileUtils,
6566
Uint8List? seedBytes,
@@ -80,6 +81,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
8081
passphrase: passphrase,
8182
xpub: xpub,
8283
walletInfo: walletInfo,
84+
derivationInfo: derivationInfo,
8385
unspentCoinsInfo: unspentCoinsInfo,
8486
network: LitecoinNetwork.mainnet,
8587
initialAddresses: initialAddresses,
@@ -166,6 +168,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
166168
{required String mnemonic,
167169
required String password,
168170
required WalletInfo walletInfo,
171+
required DerivationInfo derivationInfo,
169172
required Box<UnspentCoinsInfo> unspentCoinsInfo,
170173
required EncryptionFileUtils encryptionFileUtils,
171174
String? passphrase,
@@ -177,7 +180,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
177180
Map<String, int>? initialChangeAddressIndex}) async {
178181
late Uint8List seedBytes;
179182

180-
switch (walletInfo.derivationInfo?.derivationType) {
183+
switch (derivationInfo.derivationType) {
181184
case DerivationType.bip39:
182185
seedBytes = await bip39.mnemonicToSeed(
183186
mnemonic,
@@ -193,6 +196,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
193196
mnemonic: mnemonic,
194197
password: password,
195198
walletInfo: walletInfo,
199+
derivationInfo: derivationInfo,
196200
unspentCoinsInfo: unspentCoinsInfo,
197201
initialAddresses: initialAddresses,
198202
initialMwebAddresses: initialMwebAddresses,
@@ -243,18 +247,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
243247
);
244248
}
245249

246-
walletInfo.derivationInfo ??= DerivationInfo();
247-
250+
final derivationInfo = await walletInfo.getDerivationInfo();
248251
// set the default if not present:
249-
walletInfo.derivationInfo!.derivationPath ??= snp?.derivationPath ?? electrum_path;
250-
walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
252+
derivationInfo.derivationPath ??= snp?.derivationPath ?? electrum_path;
253+
derivationInfo.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
251254

252255
Uint8List? seedBytes = null;
253256
final mnemonic = keysData.mnemonic;
254257
final passphrase = keysData.passphrase;
255258

256259
if (mnemonic != null) {
257-
switch (walletInfo.derivationInfo?.derivationType) {
260+
switch (derivationInfo.derivationType) {
258261
case DerivationType.bip39:
259262
seedBytes = await bip39.mnemonicToSeed(
260263
mnemonic,
@@ -267,12 +270,14 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
267270
break;
268271
}
269272
}
273+
await derivationInfo.save();
270274

271275
return LitecoinWallet(
272276
mnemonic: keysData.mnemonic,
273277
xpub: keysData.xPub,
274278
password: password,
275279
walletInfo: walletInfo,
280+
derivationInfo: derivationInfo,
276281
unspentCoinsInfo: unspentCoinsInfo,
277282
initialAddresses: snp?.addresses,
278283
initialMwebAddresses: snp?.mwebAddresses,
@@ -1372,10 +1377,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
13721377
LitecoinLedgerApp? _litecoinLedgerApp;
13731378

13741379
@override
1375-
void setLedgerConnection(LedgerConnection connection) {
1380+
Future<void> setLedgerConnection(LedgerConnection connection) async {
13761381
_ledgerConnection = connection;
13771382
_litecoinLedgerApp = LitecoinLedgerApp(_ledgerConnection!,
1378-
derivationPath: walletInfo.derivationInfo!.derivationPath!);
1383+
derivationPath: derivationInfo.derivationPath!);
13791384
}
13801385

13811386
@override

0 commit comments

Comments
 (0)