@@ -108,6 +108,53 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
108
108
int initialSilentAddressIndex = 0 ,
109
109
required bool mempoolAPIEnabled,
110
110
}) async {
111
+ List <int >? seedBytes = null ;
112
+ final Map <CWBitcoinDerivationType , Bip32Slip10Secp256k1 > hdWallets = {};
113
+
114
+ if (walletInfo.isRecovery) {
115
+ for (final derivation in walletInfo.derivations ?? < DerivationInfo > []) {
116
+ if (derivation.description? .contains ("SP" ) ?? false ) {
117
+ continue ;
118
+ }
119
+
120
+ if (derivation.derivationType == DerivationType .bip39) {
121
+ seedBytes = Bip39SeedGenerator .generateFromString (mnemonic, passphrase);
122
+ hdWallets[CWBitcoinDerivationType .bip39] = Bip32Slip10Secp256k1 .fromSeed (seedBytes);
123
+
124
+ break ;
125
+ } else {
126
+ try {
127
+ seedBytes = ElectrumV2SeedGenerator .generateFromString (mnemonic, passphrase);
128
+ hdWallets[CWBitcoinDerivationType .electrum] = Bip32Slip10Secp256k1 .fromSeed (seedBytes);
129
+ } catch (e) {
130
+ print ("electrum_v2 seed error: $e " );
131
+
132
+ try {
133
+ seedBytes = ElectrumV1SeedGenerator (mnemonic).generate ();
134
+ hdWallets[CWBitcoinDerivationType .electrum] =
135
+ Bip32Slip10Secp256k1 .fromSeed (seedBytes);
136
+ } catch (e) {
137
+ print ("electrum_v1 seed error: $e " );
138
+ }
139
+ }
140
+
141
+ break ;
142
+ }
143
+ }
144
+
145
+ if (hdWallets[CWBitcoinDerivationType .bip39] != null ) {
146
+ hdWallets[CWBitcoinDerivationType .old_bip39] = hdWallets[CWBitcoinDerivationType .bip39]! ;
147
+ }
148
+ if (hdWallets[CWBitcoinDerivationType .electrum] != null ) {
149
+ hdWallets[CWBitcoinDerivationType .old_electrum] =
150
+ hdWallets[CWBitcoinDerivationType .electrum]! ;
151
+ }
152
+ } else {
153
+ seedBytes = walletInfo.derivationInfo? .derivationType == DerivationType .electrum
154
+ ? ElectrumV2SeedGenerator .generateFromString (mnemonic, passphrase)
155
+ : Bip39SeedGenerator .generateFromString (mnemonic, passphrase);
156
+ }
157
+
111
158
return BitcoinWallet (
112
159
mnemonic: mnemonic,
113
160
passphrase: passphrase ?? "" ,
@@ -119,9 +166,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
119
166
initialSilentAddressIndex: initialSilentAddressIndex,
120
167
initialBalance: initialBalance,
121
168
encryptionFileUtils: encryptionFileUtils,
122
- seedBytes: walletInfo.derivationInfo? .derivationType == DerivationType .electrum
123
- ? ElectrumV2SeedGenerator .generateFromString (mnemonic, passphrase)
124
- : Bip39SeedGenerator .generateFromString (mnemonic, passphrase),
169
+ seedBytes: seedBytes,
170
+ hdWallets: hdWallets,
125
171
initialRegularAddressIndex: initialRegularAddressIndex,
126
172
initialChangeAddressIndex: initialChangeAddressIndex,
127
173
addressPageType: addressPageType,
@@ -253,16 +299,24 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
253
299
}
254
300
255
301
Future <bool > getNodeIsElectrs () async {
256
- final version = await sendWorker (ElectrumWorkerGetVersionRequest ()) as List <String >;
302
+ if (node? .uri.host.contains ("electrs" ) ?? false ) {
303
+ return true ;
304
+ }
305
+
306
+ final version = await sendWorker (ElectrumWorkerGetVersionRequest ());
257
307
258
- if (version.isNotEmpty) {
308
+ if (version is List < String > && version .isNotEmpty) {
259
309
final server = version[0 ];
260
310
261
311
if (server.toLowerCase ().contains ('electrs' )) {
262
312
node! .isElectrs = true ;
263
313
node! .save ();
264
314
return node! .isElectrs! ;
265
315
}
316
+ } else if (version is String && version.toLowerCase ().contains ('electrs' )) {
317
+ node! .isElectrs = true ;
318
+ node! .save ();
319
+ return node! .isElectrs! ;
266
320
}
267
321
268
322
node! .isElectrs = false ;
@@ -271,33 +325,39 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
271
325
}
272
326
273
327
Future <bool > getNodeSupportsSilentPayments () async {
274
- return true ;
328
+ // TODO: handle disconnection on check
329
+ // TODO: use cached values
330
+ if (node == null ) {
331
+ return false ;
332
+ }
333
+
334
+ final isFulcrum = node! .uri.host.contains ("fulcrum" );
335
+ if (isFulcrum) {
336
+ return false ;
337
+ }
338
+
275
339
// As of today (august 2024), only ElectrumRS supports silent payments
276
- // if (!(await getNodeIsElectrs())) {
277
- // return false;
278
- // }
340
+ if (! (await getNodeIsElectrs ())) {
341
+ return false ;
342
+ }
279
343
280
- // if (node == null) {
281
- // return false;
282
- // }
344
+ try {
345
+ final workerResponse = (await sendWorker (ElectrumWorkerCheckTweaksRequest ())) as String ;
346
+ final tweaksResponse = ElectrumWorkerCheckTweaksResponse .fromJson (
347
+ json.decode (workerResponse) as Map <String , dynamic >,
348
+ );
349
+ final supportsScanning = tweaksResponse.result == true ;
283
350
284
- // try {
285
- // final tweaksResponse = await electrumClient.getTweaks(height: 0);
286
-
287
- // if (tweaksResponse != null) {
288
- // node!.supportsSilentPayments = true;
289
- // node!.save();
290
- // return node!.supportsSilentPayments!;
291
- // }
292
- // } on RequestFailedTimeoutException catch (_) {
293
- // node!.supportsSilentPayments = false;
294
- // node!.save();
295
- // return node!.supportsSilentPayments!;
296
- // } catch (_) {}
297
-
298
- // node!.supportsSilentPayments = false;
299
- // node!.save();
300
- // return node!.supportsSilentPayments!;
351
+ if (supportsScanning) {
352
+ node! .supportsSilentPayments = true ;
353
+ node! .save ();
354
+ return node! .supportsSilentPayments! ;
355
+ }
356
+ } catch (_) {}
357
+
358
+ node! .supportsSilentPayments = false ;
359
+ node! .save ();
360
+ return node! .supportsSilentPayments! ;
301
361
}
302
362
303
363
LedgerConnection ? _ledgerConnection;
@@ -383,16 +443,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
383
443
if (tip > walletInfo.restoreHeight) {
384
444
_setListeners (walletInfo.restoreHeight);
385
445
}
386
- } else {
387
- alwaysScan = false ;
388
-
389
- // _isolate?.then((value) => value.kill(priority: Isolate.immediate));
390
-
391
- // if (rpc!.isConnected) {
392
- // syncStatus = SyncedSyncStatus();
393
- // } else {
394
- // syncStatus = NotConnectedSyncStatus();
395
- // }
446
+ } else if (syncStatus is ! SyncedSyncStatus ) {
447
+ await sendWorker (ElectrumWorkerStopScanningRequest ());
448
+ await startSync ();
396
449
}
397
450
}
398
451
@@ -565,9 +618,16 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
565
618
messageJson = message as Map <String , dynamic >;
566
619
}
567
620
final workerMethod = messageJson['method' ] as String ;
621
+ final workerError = messageJson['error' ] as String ? ;
568
622
569
623
switch (workerMethod) {
570
624
case ElectrumRequestMethods .tweaksSubscribeMethod:
625
+ if (workerError != null ) {
626
+ print (messageJson);
627
+ // _onConnectionStatusChange(ConnectionStatus.failed);
628
+ break ;
629
+ }
630
+
571
631
final response = ElectrumWorkerTweaksSubscribeResponse .fromJson (messageJson);
572
632
onTweaksSyncResponse (response.result);
573
633
break ;
@@ -651,9 +711,16 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
651
711
syncStatus = SyncingSyncStatus (newSyncStatus.blocksLeft, newSyncStatus.ptc);
652
712
} else {
653
713
syncStatus = newSyncStatus;
714
+
715
+ if (newSyncStatus is SyncedSyncStatus ) {
716
+ silentPaymentsScanningActive = false ;
717
+ }
654
718
}
655
719
656
- await walletInfo.updateRestoreHeight (result.height! );
720
+ final height = result.height;
721
+ if (height != null ) {
722
+ await walletInfo.updateRestoreHeight (height);
723
+ }
657
724
}
658
725
659
726
await save ();
@@ -801,6 +868,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
801
868
case SyncingSyncStatus :
802
869
return ;
803
870
case SyncedTipSyncStatus :
871
+ silentPaymentsScanningActive = false ;
872
+
804
873
// Message is shown on the UI for 3 seconds, then reverted to synced
805
874
Timer (Duration (seconds: 3 ), () {
806
875
if (this .syncStatus is SyncedTipSyncStatus ) this .syncStatus = SyncedSyncStatus ();
0 commit comments