dev
dart 1,362 lines 47.6 KB
Raw
1 import 'dart:convert';
2 import 'dart:io' show Directory, File, Platform;
3
4 import 'package:cake_wallet/bitcoin/bitcoin.dart';
5 import 'package:cake_wallet/core/secure_storage.dart';
6 import 'package:cake_wallet/entities/balance_display_mode.dart';
7 import 'package:cake_wallet/entities/contact.dart';
8 import 'package:cake_wallet/entities/exchange_api_mode.dart';
9 import 'package:cake_wallet/entities/fiat_api_mode.dart';
10 import 'package:cake_wallet/entities/fiat_currency.dart';
11 import 'package:cake_wallet/entities/fs_migration.dart';
12 import 'package:cake_wallet/entities/haven_seed_store.dart';
13 import 'package:cake_wallet/entities/preferences_key.dart';
14 import 'package:cake_wallet/entities/secret_store_key.dart';
15 import 'package:cake_wallet/monero/monero.dart';
16 import 'package:cake_wallet/wownero/wownero.dart';
17 import 'package:collection/collection.dart';
18 import 'package:cw_core/node.dart';
19 import 'package:cake_wallet/entities/sync_status_display_mode.dart';
20 import 'package:cw_core/node_list.dart';
21 import 'package:cw_core/pathForWallet.dart';
22 import 'package:cw_core/root_dir.dart';
23 import 'package:cw_core/spl_token.dart';
24 import 'package:cw_core/utils/print_verbose.dart';
25 import 'package:cw_core/wallet_info.dart';
26 import 'package:cw_core/wallet_type.dart';
27 import 'package:encrypt/encrypt.dart' as encrypt;
28 import 'package:hive/hive.dart';
29 import 'package:shared_preferences/shared_preferences.dart';
30 import 'package:cw_core/erc20_token.dart';
31
32 const newCakeWalletMoneroUri = 'xmr-node.cakewallet.com:18081';
33 const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002';
34 const cakeWalletSilentPaymentsElectrsUri = 'electrs.cakewallet.com:50001';
35 const publicBitcoinTestnetElectrumAddress = 'electrs.cakewallet.com';
36 const publicBitcoinTestnetElectrumPort = '50002';
37 const publicBitcoinTestnetElectrumUri =
38 '$publicBitcoinTestnetElectrumAddress:$publicBitcoinTestnetElectrumPort';
39 const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002';
40 const havenDefaultNodeUri = 'nodes.havenprotocol.org:443';
41 const ethereumDefaultNodeUri = 'ethereum-rpc.publicnode.com';
42 const polygonDefaultNodeUri = 'polygon-bor-rpc.publicnode.com';
43 const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002';
44 const nanoDefaultNodeUri = 'rpc.nano.to';
45 const nanoDefaultPowNodeUri = 'rpc.nano.to';
46 const solanaDefaultNodeUri = 'solana-mainnet.core.chainstack.com';
47 const tronDefaultNodeUri = 'trx.nownodes.io';
48 const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002';
49 const wowneroDefaultNodeUri = 'node3.monerodevs.org:34568';
50 const zanoDefaultNodeUri = '37.27.100.59:10500';
51 const moneroWorldNodeUri = '.moneroworld.com';
52 const decredDefaultUri = "default-spv-nodes";
53 const dogecoinDefaultNodeUri = 'dogecoin.stackwallet.com:50022';
54 const baseDefaultNodeUri = 'base-rpc.publicnode.com';
55 const arbitrumDefaultNodeUri = 'arbitrum.nownodes.io';
56 const bscDefaultNodeUri = 'bsc-dataseed.bnbchain.org';
57 const zcashDefaultNodeUri = 'zec.rocks:443';
58
59 Future<void> defaultSettingsMigration(
60 {required int version,
61 required SharedPreferences sharedPreferences,
62 required SecureStorage secureStorage,
63 required Box<Contact> contactSource,
64 required Box<HavenSeedStore> havenSeedStore}) async {
65 if (Platform.isIOS) {
66 await ios_migrate_v1(contactSource);
67 }
68
69 // check current nodes for nullability regardless of the version
70 // await checkCurrentNodes(sharedPreferences);
71
72 final isNewInstall =
73 sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
74
75 await _validateWalletInfoBoxData();
76
77 await sharedPreferences.setBool(PreferencesKey.isNewInstall, isNewInstall);
78
79 final currentVersion =
80 sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) ?? 0;
81
82 if (currentVersion >= version) {
83 return;
84 }
85
86 final migrationVersionsLength = version - currentVersion;
87 final migrationVersions =
88 List<int>.generate(migrationVersionsLength, (i) => currentVersion + (i + 1));
89
90 /// When you add a new case, increase the initialMigrationVersion parameter in the main.dart file.
91 /// This ensures that this switch case runs the newly added case.
92 await Future.forEach(migrationVersions, (int version) async {
93 try {
94 switch (version) {
95 case 1:
96 await sharedPreferences.setString(
97 PreferencesKey.currentFiatCurrencyKey, FiatCurrency.usd.toString());
98
99 if (monero != null) {
100 await sharedPreferences.setInt(
101 PreferencesKey.currentTransactionPriorityKeyLegacy,
102 monero!.getDefaultTransactionPriority().raw);
103 }
104 await sharedPreferences.setInt(
105 PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw);
106 await sharedPreferences.setBool('save_recipient_address', true);
107 await resetToDefault();
108
109 await _changeDefaultNode(
110 sharedPreferences: sharedPreferences,
111 type: WalletType.monero,
112 currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
113 useSSL: true,
114 trusted: true,
115 );
116 await _changeDefaultNode(
117 sharedPreferences: sharedPreferences,
118 type: WalletType.bitcoin,
119 currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
120 useSSL: true,
121 );
122 await _changeDefaultNode(
123 sharedPreferences: sharedPreferences,
124 type: WalletType.litecoin,
125 currentNodePreferenceKey: PreferencesKey.currentLitecoinElectrumSererIdKey,
126 useSSL: true,
127 );
128 await _changeDefaultNode(
129 sharedPreferences: sharedPreferences,
130 type: WalletType.haven,
131 currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
132 );
133 break;
134 case 2:
135 await replaceNodesMigration();
136 await _changeDefaultNode(
137 sharedPreferences: sharedPreferences,
138 type: WalletType.monero,
139 newDefaultUri: newCakeWalletMoneroUri,
140 currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
141 useSSL: true,
142 trusted: true,
143 oldUri: [
144 'xmr-node-uk.cakewallet.com:18081',
145 'eu-node.cakewallet.io:18081',
146 'node.cakewallet.io:18081'
147 ],
148 );
149 break;
150 case 3:
151 await updateNodeTypes();
152 await addWalletNodeList(type: WalletType.bitcoin);
153
154 break;
155 case 4:
156 await _changeDefaultNode(
157 sharedPreferences: sharedPreferences,
158 type: WalletType.bitcoin,
159 newDefaultUri: newCakeWalletBitcoinUri,
160 currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
161 useSSL: true,
162 );
163 break;
164
165 case 5:
166 await addAddressesForMoneroWallets();
167 break;
168
169 case 6:
170 await updateDisplayModes(sharedPreferences);
171 break;
172
173 case 9:
174 await generateBackupPassword(secureStorage);
175 break;
176
177 case 10:
178 await changeTransactionPriorityAndFeeRateKeys(sharedPreferences);
179 break;
180
181 case 11:
182 await _changeDefaultNode(
183 sharedPreferences: sharedPreferences,
184 type: WalletType.monero,
185 newDefaultUri: newCakeWalletMoneroUri,
186 currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
187 trusted: true,
188 oldUri: ['.cakewallet.com'],
189 );
190 break;
191
192 case 12:
193 // await checkCurrentNodes(sharedPreferences);
194 break;
195
196 case 13:
197 await resetBitcoinElectrumServer(sharedPreferences);
198 break;
199
200 case 15:
201 await addWalletNodeList(type: WalletType.litecoin);
202 await _changeDefaultNode(
203 sharedPreferences: sharedPreferences,
204 type: WalletType.litecoin,
205 currentNodePreferenceKey: PreferencesKey.currentLitecoinElectrumSererIdKey,
206 );
207 // await checkCurrentNodes(sharedPreferences);
208 break;
209
210 case 16:
211 await addWalletNodeList(type: WalletType.haven);
212 await _changeDefaultNode(
213 sharedPreferences: sharedPreferences,
214 type: WalletType.haven,
215 currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
216 );
217 // await checkCurrentNodes(sharedPreferences);
218 break;
219
220 case 17:
221 await _changeDefaultNode(
222 sharedPreferences: sharedPreferences,
223 type: WalletType.haven,
224 currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
225 );
226 break;
227
228 case 18:
229 addWalletNodeList(type: WalletType.monero);
230 break;
231
232 case 19:
233 await validateBitcoinSavedTransactionPriority(sharedPreferences);
234 break;
235 case 20:
236 await migrateExchangeStatus(sharedPreferences);
237 break;
238 case 21:
239 await addWalletNodeList(type: WalletType.ethereum);
240 await _changeDefaultNode(
241 sharedPreferences: sharedPreferences,
242 type: WalletType.ethereum,
243 currentNodePreferenceKey: PreferencesKey.currentEthereumNodeIdKey,
244 );
245 break;
246 case 22:
247 await addWalletNodeList(type: WalletType.nano);
248 await addNanoPowNodeList();
249 await _changeDefaultNode(
250 sharedPreferences: sharedPreferences,
251 type: WalletType.nano,
252 currentNodePreferenceKey: PreferencesKey.currentNanoNodeIdKey,
253 );
254 await _changeDefaultNode(
255 sharedPreferences: sharedPreferences,
256 type: WalletType.nano,
257 currentNodePreferenceKey: PreferencesKey.currentNanoPowNodeIdKey,
258 newDefaultUri: nanoDefaultPowNodeUri,
259 );
260 break;
261 case 23:
262 await addWalletNodeList(type: WalletType.bitcoinCash);
263 await _changeDefaultNode(
264 sharedPreferences: sharedPreferences,
265 type: WalletType.bitcoinCash,
266 currentNodePreferenceKey: PreferencesKey.currentBitcoinCashNodeIdKey,
267 );
268 break;
269 case 24:
270 await addWalletNodeList(type: WalletType.polygon);
271 await _changeDefaultNode(
272 sharedPreferences: sharedPreferences,
273 type: WalletType.polygon,
274 currentNodePreferenceKey: PreferencesKey.currentPolygonNodeIdKey,
275 );
276 break;
277 case 25:
278 await rewriteSecureStoragePin(secureStorage: secureStorage);
279 break;
280 case 26:
281
282 /// commented out as it was a probable cause for some users to have white screen issues
283 /// maybe due to multiple access on Secure Storage at once
284 /// or long await time on start of the app
285 // await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences);
286 break;
287 case 27:
288 await addWalletNodeList(type: WalletType.solana);
289 await _changeDefaultNode(
290 sharedPreferences: sharedPreferences,
291 type: WalletType.solana,
292 currentNodePreferenceKey: PreferencesKey.currentSolanaNodeIdKey,
293 );
294 break;
295
296 case 28:
297 await _updateMoneroPriority(sharedPreferences);
298 break;
299 case 29:
300 await _changeDefaultNode(
301 sharedPreferences: sharedPreferences,
302 type: WalletType.bitcoin,
303 newDefaultUri: newCakeWalletBitcoinUri,
304 currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
305 useSSL: true,
306 oldUri: ['.cakewallet.com'],
307 );
308 break;
309 case 30:
310 await disableServiceStatusFiatDisabled(sharedPreferences);
311 break;
312 case 31:
313 await updateNanoNodeList();
314 break;
315 case 32:
316 await updateBtcNanoWalletInfos();
317 break;
318 case 33:
319 await addWalletNodeList(type: WalletType.tron);
320 await _changeDefaultNode(
321 sharedPreferences: sharedPreferences,
322 type: WalletType.tron,
323 currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
324 );
325 break;
326 case 34:
327 addWalletNodeList(type: WalletType.bitcoin);
328 case 35:
329 await _changeDefaultNode(
330 sharedPreferences: sharedPreferences,
331 type: WalletType.bitcoin,
332 newDefaultUri: newCakeWalletBitcoinUri,
333 currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
334 useSSL: true,
335 oldUri: ['electrs.cakewallet.com'],
336 );
337 break;
338 case 36:
339 await addWalletNodeList(type: WalletType.wownero);
340 await _changeDefaultNode(
341 sharedPreferences: sharedPreferences,
342 type: WalletType.wownero,
343 currentNodePreferenceKey: PreferencesKey.currentWowneroNodeIdKey,
344 );
345 break;
346 case 37:
347 // removed as it would be replaced again anyway
348 // await replaceTronDefaultNode(sharedPreferences: sharedPreferences, nodes: nodes);
349 break;
350 case 38:
351 await fixBtcDerivationPaths();
352 break;
353 case 39:
354 _fixNodesUseSSLFlag();
355 await _changeDefaultNode(
356 sharedPreferences: sharedPreferences,
357 type: WalletType.nano,
358 newDefaultUri: nanoDefaultNodeUri,
359 currentNodePreferenceKey: PreferencesKey.currentNanoNodeIdKey,
360 useSSL: true,
361 oldUri: ['rpc.nano.to'],
362 );
363 break;
364 case 40:
365 await removeMoneroWorld(sharedPreferences: sharedPreferences);
366 break;
367 case 41:
368 _changeExchangeProviderAvailability(
369 sharedPreferences,
370 providerName: "SwapTrade",
371 enabled: false,
372 );
373 addWalletNodeList(type: WalletType.bitcoin);
374 addWalletNodeList(type: WalletType.tron);
375 break;
376 case 42:
377 _fixNodesUseSSLFlag();
378 break;
379 case 43:
380 _fixNodesUseSSLFlag();
381 _changeExchangeProviderAvailability(
382 sharedPreferences,
383 providerName: "THORChain",
384 enabled: false,
385 );
386 _changeExchangeProviderAvailability(
387 sharedPreferences,
388 providerName: "SimpleSwap",
389 enabled: false,
390 );
391 break;
392 case 44:
393 _fixNodesUseSSLFlag();
394 await _changeDefaultNode(
395 sharedPreferences: sharedPreferences,
396 type: WalletType.bitcoin,
397 newDefaultUri: newCakeWalletBitcoinUri,
398 currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
399 useSSL: true,
400 oldUri: ['cakewallet.com'],
401 );
402 _changeDefaultNode(
403 sharedPreferences: sharedPreferences,
404 type: WalletType.tron,
405 newDefaultUri: tronDefaultNodeUri,
406 currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
407 useSSL: true,
408 oldUri: [
409 'tron-rpc.publicnode.com:443',
410 'api.trongrid.io',
411 ],
412 );
413 break;
414 case 45:
415 // await _backupHavenSeeds(havenSeedStore);
416
417 addWalletNodeList(type: WalletType.polygon);
418 addWalletNodeList(type: WalletType.ethereum);
419 _changeDefaultNode(
420 sharedPreferences: sharedPreferences,
421 type: WalletType.tron,
422 newDefaultUri: tronDefaultNodeUri,
423 currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
424 useSSL: true,
425 oldUri: [
426 'tron-rpc.publicnode.com:443',
427 'trx.nownodes.io',
428 ],
429 );
430 _changeDefaultNode(
431 sharedPreferences: sharedPreferences,
432 type: WalletType.solana,
433 newDefaultUri: solanaDefaultNodeUri,
434 currentNodePreferenceKey: PreferencesKey.currentSolanaNodeIdKey,
435 useSSL: true,
436 oldUri: ['rpc.ankr.com'],
437 );
438 break;
439 case 46:
440 await _fixNodesUseSSLFlag();
441 await addWalletNodeList(type: WalletType.litecoin);
442 await _changeDefaultNode(
443 sharedPreferences: sharedPreferences,
444 type: WalletType.solana,
445 newDefaultUri: solanaDefaultNodeUri,
446 currentNodePreferenceKey: PreferencesKey.currentSolanaNodeIdKey,
447 useSSL: true,
448 oldUri: [
449 'rpc.ankr.com',
450 'api.mainnet-beta.solana.com:443',
451 'solana-rpc.publicnode.com:443',
452 ],
453 );
454 await _updateNode(
455 currentUri: "ethereum.publicnode.com",
456 newUri: "ethereum-rpc.publicnode.com",
457 useSSL: true,
458 );
459 await _updateNode(
460 currentUri: "polygon-bor.publicnode.com",
461 newUri: "polygon-bor-rpc.publicnode.com",
462 useSSL: true,
463 );
464 case 47:
465 await addWalletNodeList(type: WalletType.zano);
466 await _changeDefaultNode(
467 sharedPreferences: sharedPreferences,
468 type: WalletType.zano,
469 currentNodePreferenceKey: PreferencesKey.currentZanoNodeIdKey,
470 );
471 _changeExchangeProviderAvailability(
472 sharedPreferences,
473 providerName: "SimpleSwap",
474 enabled: true,
475 );
476 _changeExchangeProviderAvailability(
477 sharedPreferences,
478 providerName: "SwapTrade",
479 enabled: false,
480 );
481 break;
482 case 48:
483 await addWalletNodeList(type: WalletType.decred);
484 await _changeDefaultNode(
485 sharedPreferences: sharedPreferences,
486 type: WalletType.decred,
487 currentNodePreferenceKey: PreferencesKey.currentDecredNodeIdKey,
488 );
489 break;
490 case 49:
491 _changeExchangeProviderAvailability(
492 sharedPreferences,
493 providerName: "SwapTrade",
494 enabled: true,
495 );
496 break;
497 case 50:
498 migrateExistingNodesToUseAutoSwitching();
499 break;
500 case 51:
501 _changeDefaultNode(
502 sharedPreferences: sharedPreferences,
503 type: WalletType.zano,
504 currentNodePreferenceKey: PreferencesKey.currentZanoNodeIdKey,
505 );
506 await addWalletNodeList(type: WalletType.dogecoin);
507 await _changeDefaultNode(
508 sharedPreferences: sharedPreferences,
509 type: WalletType.dogecoin,
510 currentNodePreferenceKey: PreferencesKey.currentDogecoinNodeIdKey,
511 );
512 break;
513 case 52:
514 await addWalletNodeList(type: WalletType.base);
515 await _changeDefaultNode(
516 sharedPreferences: sharedPreferences,
517 type: WalletType.base,
518 currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
519 );
520 break;
521 case 53:
522 await addWalletNodeList(type: WalletType.arbitrum);
523 await _changeDefaultNode(
524 sharedPreferences: sharedPreferences,
525 type: WalletType.arbitrum,
526 currentNodePreferenceKey: PreferencesKey.currentArbitrumNodeIdKey,
527 );
528 break;
529 case 54:
530 await _backupWowneroSeeds(havenSeedStore);
531 break;
532 case 55:
533 await addWalletNodeList(type: WalletType.zcash);
534 await _changeDefaultNode(
535 sharedPreferences: sharedPreferences,
536 type: WalletType.zcash,
537 currentNodePreferenceKey: PreferencesKey.currentZcashNodeIdKey,
538 );
539 case 56:
540 await sharedPreferences.setString(
541 PreferencesKey.syncStatusDisplayMode, SyncStatusDisplayMode.blocksRemaining.name);
542 break;
543 case 57:
544 await _addXautTokenToExistingEthereumWallets();
545
546 await addWalletNodeList(type: WalletType.bsc);
547 await _changeDefaultNode(
548 sharedPreferences: sharedPreferences,
549 type: WalletType.bsc,
550 currentNodePreferenceKey: PreferencesKey.currentBscNodeIdKey,
551 );
552 break;
553 case 58: // BalanceCardStyleSettings no-op (handled in sqlite.dart)
554 case 59: // WalletInfo.receiveInfoboxDismissed no-op (handled in sqlite.dart)
555 case 60: // BalanceCardStyleSettings.cardOrder no-op (handled in sqlite.dart)
556 // Do not migrate SQLite here, do that in sqlite.dart in order to prevent runtime
557 // errors, missing row and missing tables.
558 case 61:
559 // reset force dex option only 1 time and let users pick it from the swap settings preference
560 await sharedPreferences.setBool(PreferencesKey.forceDecentralizedExchanges, false);
561 break;
562 case 62:
563 await _changeExchangeProviderAvailability(
564 sharedPreferences,
565 providerName: "Swaps.XYZ",
566 enabled: false,
567 );
568 _changeExchangeProviderAvailability(
569 sharedPreferences,
570 providerName: "StealthEX",
571 enabled: false,
572 );
573 break;
574 case 63:
575 await _addXaut0TokenToExistingSolanaWallets();
576 break;
577 case 64:
578 await _backupWowneroSeeds(havenSeedStore);
579 _changeExchangeProviderAvailability(
580 sharedPreferences,
581 providerName: "LetsExchange",
582 enabled: false,
583 );
584 await _changeExchangeProviderAvailability(
585 sharedPreferences,
586 providerName: "Swaps.XYZ",
587 enabled: true,
588 );
589 break;
590 case 65:
591 await _changeDefaultNode(
592 sharedPreferences: sharedPreferences,
593 type: WalletType.base,
594 currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
595 oldUri: ['base.nownodes.io'],
596 );
597 break;
598 case 66:
599 await _changeDefaultNode(
600 sharedPreferences: sharedPreferences,
601 type: WalletType.arbitrum,
602 currentNodePreferenceKey: PreferencesKey.currentArbitrumNodeIdKey,
603 oldUri: ["arbitrum.nownodes.io"]);
604 break;
605 case 67:
606 _changeExchangeProviderAvailability(
607 sharedPreferences,
608 providerName: "LetsExchange",
609 enabled: true,
610 );
611 break;
612 case 68:
613 await _changeDefaultNode(
614 sharedPreferences: sharedPreferences,
615 type: WalletType.tron,
616 newDefaultUri: tronDefaultNodeUri,
617 currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
618 useSSL: true,
619 oldUri: [
620 'tron-rpc.publicnode.com:443',
621 'api.trongrid.io',
622 ],
623 );
624 await _changeDefaultNode(
625 sharedPreferences: sharedPreferences,
626 type: WalletType.monero,
627 newDefaultUri: newCakeWalletMoneroUri,
628 currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
629 useSSL: true,
630 trusted: true,
631 oldUri: ['nodes.hashvault.pro:18081'],
632 );
633 break;
634 case 69:
635 _changeExchangeProviderAvailability(
636 sharedPreferences,
637 providerName: "Exolix",
638 enabled: false,
639 );
640 break;
641 case 70:
642 await _addTbbTokenToExistingSolanaWallets();
643 break;
644 default:
645 break;
646 }
647
648 await sharedPreferences.setInt(
649 PreferencesKey.currentDefaultSettingsMigrationVersion, version);
650 } catch (e, s) {
651 printV('Migration error: ${e.toString()}');
652 printV('Migration error: ${s}');
653 }
654 });
655
656 await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
657 }
658
659 Future<void> _updateNode({
660 required String currentUri,
661 String? newUri,
662 bool? useSSL,
663 }) async {
664 final nodes = await Node.getAll();
665
666 for (Node node in nodes) {
667 if (node.uriRaw == currentUri) {
668 if (newUri != null) {
669 node.uriRaw = newUri;
670 }
671 if (useSSL != null) {
672 node.useSSL = useSSL;
673 }
674 await node.save();
675 }
676 }
677 }
678
679 /// generic function for changing any wallet default node
680 /// instead of making a new function for each change
681 Future<void> _changeDefaultNode({
682 required SharedPreferences sharedPreferences,
683 required WalletType type,
684 required String currentNodePreferenceKey,
685 bool useSSL = true,
686 bool trusted = false,
687 String? newDefaultUri, // ignore, if you want to use the default node uri
688 List<String>?
689 oldUri, // ignore, if you want to force replace the node regardless of the user's current node
690 }) async {
691 List<Node> nodes = await Node.getAll();
692
693 final currentNodeId = sharedPreferences.getInt(currentNodePreferenceKey);
694 final bool shouldReplace;
695 if (currentNodeId == null) {
696 shouldReplace = true;
697 } else {
698 final currentNode = nodes.firstWhereOrNull((node) => node.id == currentNodeId);
699 shouldReplace =
700 currentNode == null || (oldUri?.any((e) => currentNode.uriRaw.contains(e)) ?? true);
701 }
702
703 if (shouldReplace) {
704 newDefaultUri ??= (await getDefaultNodeFromFiles(type)).uriRaw;
705 var newNodeId = nodes.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.id;
706
707 // new node doesn't exist, then add it
708 if (newNodeId == null) {
709 final newNode = Node(
710 uri: newDefaultUri,
711 type: type,
712 useSSL: useSSL,
713 trusted: trusted,
714 );
715
716 await newNode.save();
717 newNodeId = newNode.id;
718 }
719
720 await sharedPreferences.setInt(currentNodePreferenceKey, newNodeId);
721 }
722 }
723
724 Future<void> _changeExchangeProviderAvailability(SharedPreferences sharedPreferences,
725 {required String providerName, required bool enabled}) async {
726 final Map<String, dynamic> exchangeProvidersSelection =
727 json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
728 as Map<String, dynamic>;
729
730 exchangeProvidersSelection[providerName] = enabled;
731
732 await sharedPreferences.setString(
733 PreferencesKey.exchangeProvidersSelection,
734 json.encode(exchangeProvidersSelection),
735 );
736 }
737
738 Future<void> _fixNodesUseSSLFlag() async {
739 final nodes = await Node.getAll();
740 for (Node node in nodes) {
741 switch (node.uriRaw) {
742 case cakeWalletLitecoinElectrumUri:
743 case cakeWalletBitcoinElectrumUri:
744 case newCakeWalletBitcoinUri:
745 case newCakeWalletMoneroUri:
746 node.useSSL = true;
747 node.trusted = true;
748 await node.save();
749 }
750 }
751 }
752
753 Future<void> updateNanoNodeList() async {
754 final nodes = await Node.getAll();
755 final nodeList = await loadDefaultNodes(WalletType.nano);
756 var listOfNewEndpoints = <String>[
757 "app.natrium.io",
758 "rainstorm.city",
759 "node.somenano.com",
760 "nanoslo.0x.no",
761 "www.bitrequest.app",
762 ];
763 // add new nodes:
764 for (final node in nodeList) {
765 if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.contains(node)) {
766 await node.save();
767 }
768 }
769
770 // update the nautilus node:
771 final nautilusNode = nodes.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
772 if (nautilusNode != null) {
773 nautilusNode.uriRaw = "node.nautilus.io";
774 nautilusNode.path = "/api";
775 nautilusNode.useSSL = true;
776 await nautilusNode.save();
777 }
778 }
779
780 Future<void> disableServiceStatusFiatDisabled(SharedPreferences sharedPreferences) async {
781 final currentFiat = await sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1;
782 if (currentFiat == -1 || currentFiat == FiatApiMode.enabled.raw) {
783 return;
784 }
785
786 if (currentFiat == FiatApiMode.disabled.raw || currentFiat == FiatApiMode.torOnly.raw) {
787 await sharedPreferences.setBool(PreferencesKey.disableBulletinKey, true);
788 }
789 }
790
791 Future<void> _backupWowneroSeeds(Box<HavenSeedStore> havenSeedStore) async {
792 final future = wownero?.backupSeeds(havenSeedStore);
793 if (future != null) await future;
794 return;
795 }
796
797 Future<void> _updateMoneroPriority(SharedPreferences sharedPreferences) async {
798 if (monero == null) {
799 return;
800 }
801
802 final currentPriority =
803 await sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority) ??
804 monero!.getDefaultTransactionPriority().serialize();
805
806 // was set to automatic but automatic should be 0
807 if (currentPriority == 1) {
808 sharedPreferences.setInt(PreferencesKey.moneroTransactionPriority,
809 monero!.getDefaultTransactionPriority().serialize()); // 0
810 }
811 }
812
813 Future<void> _validateWalletInfoBoxData() async {
814 try {
815 final root = await getAppDir();
816
817 for (var type in WalletType.values) {
818 if (type == WalletType.none) {
819 continue;
820 }
821
822 String prefix = walletTypeToString(type).toLowerCase();
823 Directory walletsDir = Directory('${root.path}/wallets/$prefix/');
824
825 if (!walletsDir.existsSync()) {
826 continue;
827 }
828
829 List<String> walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList();
830
831 for (var name in walletNames) {
832 final Directory dir;
833 try {
834 dir = Directory(await pathForWalletDir(name: name, type: type));
835 } catch (_) {
836 continue;
837 }
838
839 final walletFiles = dir.listSync();
840 final hasCacheFile = walletFiles.any((element) => element.path.contains("$name/$name"));
841
842 if (!hasCacheFile) {
843 continue;
844 }
845
846 if (type == WalletType.monero || type == WalletType.haven) {
847 final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys"));
848
849 if (!hasKeysFile) {
850 continue;
851 }
852 }
853
854 final id = prefix + '_' + name;
855 final exist = (await WalletInfo.getAll()).any((el) => el.id == id);
856
857 if (exist) {
858 continue;
859 }
860
861 final walletInfo = WalletInfo.external(
862 id: id,
863 type: type,
864 name: name,
865 isRecovery: true,
866 restoreHeight: 0,
867 date: DateTime.now(),
868 dirPath: dir.path,
869 path: '${dir.path}/$name',
870 address: '',
871 showIntroCakePayCard: false,
872 );
873
874 await walletInfo.save();
875 }
876 }
877 } catch (_) {}
878 }
879
880 Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async {
881 if (bitcoin == null) {
882 return;
883 }
884 final int? savedBitcoinPriority =
885 sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority);
886 if (!bitcoin!.getTransactionPriorities().any((element) => element.raw == savedBitcoinPriority)) {
887 await sharedPreferences.setInt(PreferencesKey.bitcoinTransactionPriority,
888 bitcoin!.getMediumTransactionPriority().serialize());
889 }
890 }
891
892 Future<void> replaceNodesMigration() async {
893 final replaceNodes = <String, Node>{
894 'eu-node.cakewallet.io:18081':
895 Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
896 'node.cakewallet.io:18081':
897 Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
898 'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081', type: WalletType.monero)
899 };
900
901 List<Node> nodes = await Node.getAll();
902 nodes.forEach((Node node) async {
903 final nodeToReplace = replaceNodes[node.uri];
904
905 if (nodeToReplace != null) {
906 node.uriRaw = nodeToReplace.uriRaw;
907 node.login = nodeToReplace.login;
908 node.password = nodeToReplace.password;
909 await node.save();
910 }
911 });
912 }
913
914 Future<Node?> getBitcoinTestnetDefaultElectrumServer() async {
915 final nodes = await Node.getAll();
916
917 return nodes.firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
918 nodes.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
919 }
920
921 Future<void> insecureStorageMigration({
922 required SharedPreferences sharedPreferences,
923 required SecureStorage secureStorage,
924 }) async {
925 bool? allowBiometricalAuthentication =
926 sharedPreferences.getBool(SecureKey.allowBiometricalAuthenticationKey);
927 bool? useTOTP2FA = sharedPreferences.getBool(SecureKey.useTOTP2FA);
928 bool? shouldRequireTOTP2FAForAccessingWallet =
929 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForAccessingWallet);
930 bool? shouldRequireTOTP2FAForSendsToContact =
931 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForSendsToContact);
932 bool? shouldRequireTOTP2FAForSendsToNonContact =
933 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForSendsToNonContact);
934 bool? shouldRequireTOTP2FAForSendsToInternalWallets =
935 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets);
936 bool? shouldRequireTOTP2FAForExchangesToInternalWallets =
937 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets);
938 bool? shouldRequireTOTP2FAForExchangesToExternalWallets =
939 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets);
940 bool? shouldRequireTOTP2FAForAddingContacts =
941 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForAddingContacts);
942 bool? shouldRequireTOTP2FAForCreatingNewWallets =
943 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForCreatingNewWallets);
944 bool? shouldRequireTOTP2FAForAllSecurityAndBackupSettings =
945 sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings);
946 int? selectedCake2FAPreset = sharedPreferences.getInt(SecureKey.selectedCake2FAPreset);
947 String? totpSecretKey = sharedPreferences.getString(SecureKey.totpSecretKey);
948 int? pinTimeOutDuration = sharedPreferences.getInt(SecureKey.pinTimeOutDuration);
949 int? lastAuthTimeMilliseconds = sharedPreferences.getInt(SecureKey.lastAuthTimeMilliseconds);
950
951 try {
952 await secureStorage.write(
953 key: SecureKey.allowBiometricalAuthenticationKey,
954 value: allowBiometricalAuthentication.toString());
955 await secureStorage.write(key: SecureKey.useTOTP2FA, value: useTOTP2FA.toString());
956 await secureStorage.write(
957 key: SecureKey.shouldRequireTOTP2FAForAccessingWallet,
958 value: shouldRequireTOTP2FAForAccessingWallet.toString());
959 await secureStorage.write(
960 key: SecureKey.shouldRequireTOTP2FAForSendsToContact,
961 value: shouldRequireTOTP2FAForSendsToContact.toString());
962 await secureStorage.write(
963 key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact,
964 value: shouldRequireTOTP2FAForSendsToNonContact.toString());
965 await secureStorage.write(
966 key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets,
967 value: shouldRequireTOTP2FAForSendsToInternalWallets.toString());
968 await secureStorage.write(
969 key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets,
970 value: shouldRequireTOTP2FAForExchangesToInternalWallets.toString());
971 await secureStorage.write(
972 key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets,
973 value: shouldRequireTOTP2FAForExchangesToExternalWallets.toString());
974 await secureStorage.write(
975 key: SecureKey.shouldRequireTOTP2FAForAddingContacts,
976 value: shouldRequireTOTP2FAForAddingContacts.toString());
977 await secureStorage.write(
978 key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets,
979 value: shouldRequireTOTP2FAForCreatingNewWallets.toString());
980 await secureStorage.write(
981 key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
982 value: shouldRequireTOTP2FAForAllSecurityAndBackupSettings.toString());
983 await secureStorage.write(
984 key: SecureKey.selectedCake2FAPreset, value: selectedCake2FAPreset.toString());
985 await secureStorage.write(key: SecureKey.totpSecretKey, value: totpSecretKey.toString());
986 await secureStorage.write(
987 key: SecureKey.pinTimeOutDuration, value: pinTimeOutDuration.toString());
988 await secureStorage.write(
989 key: SecureKey.lastAuthTimeMilliseconds, value: lastAuthTimeMilliseconds.toString());
990 } catch (e) {
991 printV("Error migrating shared preferences to secure storage!: $e");
992 // this actually shouldn't be that big of a problem since we don't delete the old keys in this update
993 // and we read and write to the new locations when loading storage, the migration is just for extra safety
994 }
995 }
996
997 Future<void> rewriteSecureStoragePin({required SecureStorage secureStorage}) async {
998 // the bug only affects ios/mac:
999 if (!Platform.isIOS && !Platform.isMacOS) {
1000 return;
1001 }
1002
1003 // first, get the encoded pin:
1004 final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
1005 String? encodedPin;
1006 try {
1007 encodedPin = await secureStorage.read(key: keyForPinCode);
1008 } catch (e) {
1009 // either we don't have a pin, or we can't read it (maybe even because of the bug!)
1010 // the only option here is to abort the migration or we risk losing the pin and locking the user out
1011 return;
1012 }
1013
1014 if (encodedPin == null) {
1015 return;
1016 }
1017
1018 // ensure we overwrite by deleting the old key first:
1019 await secureStorage.delete(key: keyForPinCode);
1020 await secureStorage.write(
1021 key: keyForPinCode,
1022 value: encodedPin,
1023 // TODO: find a way to add those with the generated secure storage
1024 // iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
1025 // mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
1026 );
1027 }
1028
1029 Future<void> updateNodeTypes() async {
1030 List<Node> nodes = await Node.getAll();
1031 nodes.forEach((node) async {
1032 if (node.type == null) {
1033 node.type = WalletType.monero;
1034 await node.save();
1035 }
1036 });
1037 }
1038
1039 Future<void> addAddressesForMoneroWallets() async {
1040 final moneroWalletsInfo =
1041 (await WalletInfo.getAll()).where((info) => info.type == WalletType.monero);
1042 moneroWalletsInfo.forEach((info) async {
1043 try {
1044 final walletPath = await pathForWallet(name: info.name, type: WalletType.monero);
1045 final addressFilePath = '$walletPath.address.txt';
1046 final addressFile = File(addressFilePath);
1047
1048 if (!addressFile.existsSync()) {
1049 return;
1050 }
1051
1052 final addressText = await addressFile.readAsString();
1053 info.address = addressText;
1054 await info.save();
1055 } catch (e) {
1056 printV(e.toString());
1057 }
1058 });
1059 }
1060
1061 Future<void> updateDisplayModes(SharedPreferences sharedPreferences) async {
1062 final currentBalanceDisplayMode =
1063 sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey) ?? -1;
1064 final balanceDisplayMode = currentBalanceDisplayMode < 2 ? 3 : 2;
1065 await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
1066 }
1067
1068 Future<void> generateBackupPassword(SecureStorage secureStorage) async {
1069 final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
1070
1071 if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) {
1072 return;
1073 }
1074
1075 final password = encrypt.Key.fromSecureRandom(32).base16;
1076 await secureStorage.delete(key: key);
1077 await secureStorage.write(key: key, value: password);
1078 }
1079
1080 Future<void> changeTransactionPriorityAndFeeRateKeys(SharedPreferences sharedPreferences) async {
1081 final legacyTransactionPriority =
1082 sharedPreferences.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy);
1083 if (legacyTransactionPriority != null) {
1084 await sharedPreferences.setInt(
1085 PreferencesKey.moneroTransactionPriority, legacyTransactionPriority);
1086 }
1087 if (bitcoin != null) {
1088 await sharedPreferences.setInt(PreferencesKey.bitcoinTransactionPriority,
1089 bitcoin!.getMediumTransactionPriority().serialize());
1090 }
1091 }
1092
1093 Future<void> fixBtcDerivationPaths() async {
1094 for (WalletInfo walletInfo in await WalletInfo.getAll()) {
1095 if (walletInfo.type == WalletType.bitcoin ||
1096 walletInfo.type == WalletType.bitcoinCash ||
1097 walletInfo.type == WalletType.litecoin) {
1098 final derivationInfo = await walletInfo.getDerivationInfo();
1099 if (derivationInfo?.derivationPath == "m/0'/0") {
1100 derivationInfo!.derivationPath = "m/0'";
1101 await walletInfo.save();
1102 }
1103 }
1104 }
1105 }
1106
1107 Future<void> updateBtcNanoWalletInfos() async {}
1108 // Future<void> updateBtcNanoWalletInfos() async {
1109 // for (WalletInfo walletInfo in await WalletInfo.getAll()) {
1110 // if (walletInfo.type == WalletType.nano || walletInfo.type == WalletType.bitcoin) {
1111 // final derivationInfo = await walletInfo.getDerivationInfo();
1112 // derivationInfo = DerivationInfo(
1113 // derivationPath: derivationInfo?.derivationPath,
1114 // derivationType: derivationInfo?.derivationType,
1115 // address: walletInfo.address,
1116 // transactionsCount: walletInfo.restoreHeight,
1117 // );
1118 // await walletInfo.save();
1119 // }
1120 // }
1121 // }
1122
1123 Future<void> resetBitcoinElectrumServer(SharedPreferences sharedPreferences) async {
1124 final nodeSource = await Node.getAll();
1125 final currentElectrumSeverId =
1126 sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
1127 final oldElectrumServer = nodeSource
1128 .firstWhereOrNull((node) => node.uri.toString().contains('electrumx.cakewallet.com'));
1129 var cakeWalletNode =
1130 nodeSource.firstWhereOrNull((node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
1131
1132 if (cakeWalletNode == null) {
1133 cakeWalletNode = Node(
1134 uri: cakeWalletBitcoinElectrumUri,
1135 type: WalletType.bitcoin,
1136 useSSL: false,
1137 isEnabledForAutoSwitching: true);
1138 // final cakeWalletElectrumTestnet =
1139 // Node(uri: publicBitcoinTestnetElectrumUri, type: WalletType.bitcoin, useSSL: false);
1140 // await nodeSource.add(cakeWalletElectrumTestnet);
1141 await cakeWalletNode.save();
1142 }
1143
1144 if (currentElectrumSeverId == oldElectrumServer?.id) {
1145 await sharedPreferences.setInt(
1146 PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletNode.id);
1147 }
1148
1149 await oldElectrumServer?.delete();
1150 }
1151
1152 Future<void> migrateExchangeStatus(SharedPreferences sharedPreferences) async {
1153 final isExchangeDisabled = sharedPreferences.getBool(PreferencesKey.disableExchangeKey);
1154 if (isExchangeDisabled == null) {
1155 return;
1156 }
1157
1158 await sharedPreferences.setInt(PreferencesKey.exchangeStatusKey,
1159 isExchangeDisabled ? ExchangeApiMode.disabled.raw : ExchangeApiMode.enabled.raw);
1160
1161 await sharedPreferences.remove(PreferencesKey.disableExchangeKey);
1162 }
1163
1164 Future<void> addNanoPowNodeList() async {
1165 final nodeList = await loadDefaultNanoPowNodes();
1166 final nodes = await Node.getAllPow();
1167 for (var node in nodeList) {
1168 if (nodes.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
1169 await node.save();
1170 }
1171 }
1172 }
1173
1174 Future<Node?> getNanoDefaultPowNode() async {
1175 final nodes = await Node.getAll();
1176 return nodes.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
1177 nodes.firstWhereOrNull((node) => (node.type == WalletType.nano));
1178 }
1179
1180 Future<void> addWalletNodeList({required WalletType type}) async {
1181 final nodes = await Node.getAll();
1182 final List<Node> nodeList = await loadDefaultNodes(type);
1183 for (var node in nodeList) {
1184 if (nodes.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
1185 await node.save();
1186 }
1187 }
1188 }
1189
1190 Future<void> removeMoneroWorld({required SharedPreferences sharedPreferences}) async {
1191 final nodes = await Node.getAll();
1192 const cakeWalletMoneroNodeUriPattern = '.moneroworld.com';
1193 final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
1194 final currentMoneroNode = nodes.firstWhere((node) => node.id == currentMoneroNodeId);
1195 final needToReplaceCurrentMoneroNode =
1196 currentMoneroNode.uri.toString().contains(cakeWalletMoneroNodeUriPattern);
1197
1198 nodes.forEach((node) async {
1199 if (node.type == WalletType.monero &&
1200 node.uri.toString().contains(cakeWalletMoneroNodeUriPattern)) {
1201 await node.delete();
1202 }
1203 });
1204
1205 if (needToReplaceCurrentMoneroNode) {
1206 await _changeDefaultNode(
1207 sharedPreferences: sharedPreferences,
1208 type: WalletType.monero,
1209 newDefaultUri: newCakeWalletMoneroUri,
1210 currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
1211 trusted: true,
1212 );
1213 }
1214 }
1215
1216 Future<void> migrateExistingNodesToUseAutoSwitching() async {
1217 final listOfDefaultNodesWithAutoSwitching = [
1218 'bitcoincash.stackwallet.com:50002',
1219 'bch.aftrek.org:50002',
1220 'btc-electrum.cakewallet.com:50002',
1221 'fulcrum.sethforprivacy.com:50002',
1222 'default-spv-nodes',
1223 'dcrd.sethforprivacy.com:9108',
1224 'ethereum-rpc.publicnode.com',
1225 'eth.nownodes.io',
1226 'ltc-electrum.cakewallet.com:50002',
1227 'litecoin.stackwallet.com:20063',
1228 'nano.nownodes.io',
1229 'rpc.nano.to',
1230 'node.nautilus.io',
1231 'rpc.nano.to',
1232 'workers.perish.co',
1233 'worker.nanoriver.cc',
1234 'xmr-node.cakewallet.com:18081',
1235 'node.sethforprivacy.com:443',
1236 'nodes.hashvault.pro:18081',
1237 'polygon-bor-rpc.publicnode.com',
1238 'matic.nownodes.io',
1239 'api.mainnet-beta.solana.com:443',
1240 'solana-rpc.publicnode.com:443',
1241 'solana-mainnet.core.chainstack.com',
1242 'api.trongrid.io',
1243 'trx.nownodes.io',
1244 'node3.monerodevs.org:34568',
1245 'node2.monerodevs.org:34568',
1246 '37.27.100.59:10500',
1247 'zano.cakewallet.com:11211',
1248 'electrum.cakewallet.com:50002',
1249 ];
1250 final nodes = await Node.getAll();
1251 for (var node in nodes) {
1252 if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
1253 node.isEnabledForAutoSwitching = true;
1254 await node.save();
1255 }
1256 }
1257
1258 final powNodes = await Node.getAllPow();
1259
1260 for (var node in powNodes) {
1261 if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
1262 node.isEnabledForAutoSwitching = true;
1263 node.isPow = true;
1264 await node.save();
1265 }
1266 }
1267 }
1268
1269 Future<void> _addXautTokenToExistingEthereumWallets() async {
1270 try {
1271 final xautToken = Erc20Token(
1272 name: "Tether Gold",
1273 symbol: "XAUT",
1274 contractAddress: "0x68749665FF8D2d112Fa859AA293F07A622782F38",
1275 decimal: 6,
1276 enabled: false,
1277 iconPath: "assets/images/xaut_icon.png",
1278 );
1279
1280 final allWallets = await WalletInfo.getAll();
1281
1282 final ethereumWallets =
1283 allWallets.where((wallet) => wallet.type == WalletType.ethereum).toList();
1284 const ethereumChainId = 1;
1285
1286 for (final walletInfo in ethereumWallets) {
1287 final existingToken = await Erc20Token.getByContract(
1288 walletInfo.name,
1289 ethereumChainId,
1290 xautToken.contractAddress,
1291 );
1292
1293 if (existingToken != null) continue;
1294
1295 await Erc20Token.copyWith(
1296 xautToken,
1297 walletName: walletInfo.name,
1298 chainId: ethereumChainId,
1299 ).save();
1300 }
1301 } catch (e) {
1302 printV('Error in XAUT migration: $e');
1303 }
1304 }
1305
1306 Future<void> _addXaut0TokenToExistingSolanaWallets() async {
1307 try {
1308 final xaut0Token = SPLToken(
1309 name: "Tether Gold",
1310 symbol: "XAUT0",
1311 mintAddress: "AymATz4TCL9sWNEEV9Kvyz45CHVhDZ6kUgjTJPzLpU9P",
1312 decimal: 6,
1313 mint: 'xaut0',
1314 enabled: false,
1315 iconPath: "assets/images/xau_sol.png",
1316 );
1317
1318 final allWallets = await WalletInfo.getAll();
1319
1320 final solanaWallets = allWallets.where((wallet) => wallet.type == WalletType.solana).toList();
1321
1322 for (final walletInfo in solanaWallets) {
1323 final existingToken = await SPLToken.getByMint(walletInfo.name, xaut0Token.mintAddress);
1324
1325 if (existingToken != null) continue;
1326
1327 await SPLToken.copyWith(xaut0Token, walletName: walletInfo.name).save();
1328 }
1329 } catch (e) {
1330 printV('Error in XAUT0 migration: $e');
1331 }
1332 }
1333
1334 Future<void> _addTbbTokenToExistingSolanaWallets() async {
1335 try {
1336 final tbbToken = SPLToken(
1337 name: "The Bitcoin Bull",
1338 symbol: "TBB",
1339 mintAddress: "42cXQvAAr7hcPBPWAS4ocVtDyeJ4Fa6gRR2uG4gppump",
1340 decimal: 6,
1341 mint: "tbb",
1342 enabled: false,
1343 iconPath: "assets/images/tbb_icon.png",
1344 );
1345
1346 final allWallets = await WalletInfo.getAll();
1347
1348 final solanaWallets = allWallets.where((wallet) => wallet.type == WalletType.solana).toList();
1349
1350 for (final walletInfo in solanaWallets) {
1351 final existingToken = await SPLToken.getByMint(walletInfo.name, tbbToken.mintAddress);
1352
1353 if (existingToken != null) {
1354 continue;
1355 }
1356
1357 await SPLToken.copyWith(tbbToken, walletName: walletInfo.name).save();
1358 }
1359 } catch (e) {
1360 printV("Error in TBB migration: $e");
1361 }
1362 }