Node Auto-reconnect and connectivity enhancements (#1513)

* Add auto-reconnect Enhance connectivity issues * minor enhancement [skip ci] * minor: remove core secrets since it's empty * pending transactions fix * temporary fix for RBF * remove unused hashes from cache key * fix minimum limits check * Add authentication to services api * update polyseed * override hashlib package

Omar Hatem committed Jul 6, 2024 at 17:42 UTC f902a644db68ab96fe21c80f138a74f3e04bbb3e
19 files changed +128 -219
.github/workflows/pr_test_build.yml
+1 -1
@@ -80,7 +80,7 @@ jobs:
80 /opt/android/cake_wallet/cw_monero/ios/External
81 /opt/android/cake_wallet/cw_shared_external/ios/External
82 /opt/android/cake_wallet/scripts/monero_c/release
83 - key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh', '**/build_haven.sh', '**/monero_api.cpp') }}
83 + key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh') }}
84
85 - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
86 name: Generate Externals
assets/litecoin_electrum_server_list.yml
+3 -1
@@ -1,2 +1,4 @@
1 -
2 - uri: ltc-electrum.cakewallet.com:50002
\ No newline at end of file
2 + uri: ltc-electrum.cakewallet.com:50002
3 + useSSL: true
4 + isDefault: true
\ No newline at end of file
cw_bitcoin/lib/electrum_wallet.dart
+35 -20
@@ -97,26 +97,7 @@ abstract class ElectrumWalletBase
97 this.walletInfo = walletInfo;
98 transactionHistory = ElectrumTransactionHistory(walletInfo: walletInfo, password: password);
99
100 - reaction((_) => syncStatus, (SyncStatus syncStatus) async {
101 - if (syncStatus is! AttemptingSyncStatus && syncStatus is! SyncedTipSyncStatus) {
102 - silentPaymentsScanningActive = syncStatus is SyncingSyncStatus;
103 - }
104 -
105 - if (syncStatus is NotConnectedSyncStatus) {
106 - // Needs to re-subscribe to all scripthashes when reconnected
107 - _scripthashesUpdateSubject = {};
108 -
109 - // TODO: double check this and make sure it doesn't cause any un-necessary calls
110 - // await this.electrumClient.connectToUri(node!.uri, useSSL: node!.useSSL);
111 - }
112 -
113 - // Message is shown on the UI for 3 seconds, revert to synced
114 - if (syncStatus is SyncedTipSyncStatus) {
115 - Timer(Duration(seconds: 3), () {
116 - if (this.syncStatus is SyncedTipSyncStatus) this.syncStatus = SyncedSyncStatus();
117 - });
118 - }
119 - });
100 + reaction((_) => syncStatus, _syncStatusReaction);
101 }
102
103 static bitcoin.HDWallet getAccountHDWallet(
@@ -201,6 +182,8 @@ abstract class ElectrumWalletBase
182 @observable
183 bool silentPaymentsScanningActive = false;
184
185 + bool _isTryingToConnect = false;
186 +
187 @action
188 Future<void> setSilentPaymentsScanning(bool active, bool usingElectrs) async {
189 silentPaymentsScanningActive = active;
@@ -1830,6 +1813,38 @@ abstract class ElectrumWalletBase
1813 syncStatus = NotConnectedSyncStatus();
1814 }
1815 }
1816 +
1817 + void _syncStatusReaction(SyncStatus syncStatus) async {
1818 + if (syncStatus is! AttemptingSyncStatus && syncStatus is! SyncedTipSyncStatus) {
1819 + silentPaymentsScanningActive = syncStatus is SyncingSyncStatus;
1820 + }
1821 +
1822 + if (syncStatus is NotConnectedSyncStatus) {
1823 + // Needs to re-subscribe to all scripthashes when reconnected
1824 + _scripthashesUpdateSubject = {};
1825 +
1826 + if (_isTryingToConnect) return;
1827 +
1828 + _isTryingToConnect = true;
1829 +
1830 + Future.delayed(Duration(seconds: 10), () {
1831 + if (this.syncStatus is! SyncedSyncStatus && this.syncStatus is! SyncedTipSyncStatus) {
1832 + this.electrumClient.connectToUri(
1833 + node!.uri,
1834 + useSSL: node!.useSSL ?? false,
1835 + );
1836 + }
1837 + _isTryingToConnect = false;
1838 + });
1839 + }
1840 +
1841 + // Message is shown on the UI for 3 seconds, revert to synced
1842 + if (syncStatus is SyncedTipSyncStatus) {
1843 + Timer(Duration(seconds: 3), () {
1844 + if (this.syncStatus is SyncedTipSyncStatus) this.syncStatus = SyncedSyncStatus();
1845 + });
1846 + }
1847 + }
1848 }
1849
1850 class ScanNode {
cw_bitcoin/pubspec.lock
+2 -2
@@ -866,10 +866,10 @@ packages:
866 dependency: transitive
867 description:
868 name: unorm_dart
869 - sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b"
869 + sha256: "23d8bf65605401a6a32cff99435fed66ef3dab3ddcad3454059165df46496a3b"
870 url: "https://pub.dev"
871 source: hosted
872 - version: "0.2.0"
872 + version: "0.3.0"
873 vector_math:
874 dependency: transitive
875 description:
cw_core/lib/node.dart
+3
@@ -227,6 +227,9 @@ class Node extends HiveObject with Keyable {
227 }
228 }
229
230 + // TODO: this will return true most of the time, even if the node has useSSL set to true while
231 + // it doesn't support SSL or vice versa, because it will connect normally, but it will fail if
232 + // you try to communicate with it
233 Future<bool> requestElectrumServer() async {
234 try {
235 if (useSSL == true) {
cw_haven/pubspec.lock
+8
@@ -655,6 +655,14 @@ packages:
655 url: "https://pub.dev"
656 source: hosted
657 version: "1.3.1"
658 + unorm_dart:
659 + dependency: transitive
660 + description:
661 + name: unorm_dart
662 + sha256: "23d8bf65605401a6a32cff99435fed66ef3dab3ddcad3454059165df46496a3b"
663 + url: "https://pub.dev"
664 + source: hosted
665 + version: "0.3.0"
666 vector_math:
667 dependency: transitive
668 description:
cw_monero/pubspec.lock
+10 -2
@@ -543,10 +543,10 @@ packages:
543 dependency: "direct main"
544 description:
545 name: polyseed
546 - sha256: a340962242d7917b0f3e6bd02c4acc3f90eae8ff766f1244f793ae7a6414dd68
546 + sha256: edf28042e7b0b28f97a0469aa98e6e4015937cef6b9340cd6ad2822139c95217
547 url: "https://pub.dev"
548 source: hosted
549 - version: "0.0.4"
549 + version: "0.0.5"
550 pool:
551 dependency: transitive
552 description:
@@ -696,6 +696,14 @@ packages:
696 url: "https://pub.dev"
697 source: hosted
698 version: "1.3.1"
699 + unorm_dart:
700 + dependency: transitive
701 + description:
702 + name: unorm_dart
703 + sha256: "23d8bf65605401a6a32cff99435fed66ef3dab3ddcad3454059165df46496a3b"
704 + url: "https://pub.dev"
705 + source: hosted
706 + version: "0.3.0"
707 vector_math:
708 dependency: transitive
709 description:
cw_nano/pubspec.lock
+8
@@ -805,6 +805,14 @@ packages:
805 url: "https://pub.dev"
806 source: hosted
807 version: "1.3.2"
808 + unorm_dart:
809 + dependency: transitive
810 + description:
811 + name: unorm_dart
812 + sha256: "23d8bf65605401a6a32cff99435fed66ef3dab3ddcad3454059165df46496a3b"
813 + url: "https://pub.dev"
814 + source: hosted
815 + version: "0.3.0"
816 vector_math:
817 dependency: transitive
818 description:
cw_wownero/pubspec.lock
+10 -2
@@ -543,10 +543,10 @@ packages:
543 dependency: "direct main"
544 description:
545 name: polyseed
546 - sha256: a340962242d7917b0f3e6bd02c4acc3f90eae8ff766f1244f793ae7a6414dd68
546 + sha256: edf28042e7b0b28f97a0469aa98e6e4015937cef6b9340cd6ad2822139c95217
547 url: "https://pub.dev"
548 source: hosted
549 - version: "0.0.4"
549 + version: "0.0.5"
550 pool:
551 dependency: transitive
552 description:
@@ -696,6 +696,14 @@ packages:
696 url: "https://pub.dev"
697 source: hosted
698 version: "1.3.1"
699 + unorm_dart:
700 + dependency: transitive
701 + description:
702 + name: unorm_dart
703 + sha256: "23d8bf65605401a6a32cff99435fed66ef3dab3ddcad3454059165df46496a3b"
704 + url: "https://pub.dev"
705 + source: hosted
706 + version: "0.3.0"
707 vector_math:
708 dependency: transitive
709 description:
cw_wownero/pubspec.yaml
+1 -1
@@ -19,7 +19,7 @@ dependencies:
19 flutter_mobx: ^2.0.6+1
20 intl: ^0.18.0
21 encrypt: ^5.0.1
22 - polyseed: ^0.0.4
22 + polyseed: ^0.0.5
23 cw_core:
24 path: ../cw_core
25 monero:
lib/bitcoin/cw_bitcoin.dart
+1 -1
@@ -438,7 +438,7 @@ class CWBitcoin extends Bitcoin {
438 @override
439 int getMaxCustomFeeRate(Object wallet) {
440 final bitcoinWallet = wallet as ElectrumWallet;
441 - return (bitcoinWallet.feeRate(BitcoinTransactionPriority.fast) * 1.1).round();
441 + return (bitcoinWallet.feeRate(BitcoinTransactionPriority.fast) * 10).round();
442 }
443
444 @override
lib/entities/default_settings_migration.dart
+12
@@ -242,6 +242,7 @@ Future<void> defaultSettingsMigration(
242 await fixBtcDerivationPaths(walletInfoSource);
243 break;
244 case 39:
245 + _fixNodesUseSSLFlag(nodes);
246 await changeDefaultNanoNode(nodes, sharedPreferences);
247 break;
248 default:
@@ -258,6 +259,17 @@ Future<void> defaultSettingsMigration(
259 await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
260 }
261
262 +void _fixNodesUseSSLFlag(Box<Node> nodes) {
263 + for (Node node in nodes.values) {
264 + switch (node.uriRaw) {
265 + case cakeWalletLitecoinElectrumUri:
266 + case cakeWalletBitcoinElectrumUri:
267 + node.useSSL = true;
268 + break;
269 + }
270 + }
271 +}
272 +
273 Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
274 final nodeList = await loadDefaultNanoNodes();
275 var listOfNewEndpoints = <String>[
lib/src/screens/ionia/auth/ionia_create_account_page.dart deleted
-163
@@ -1,163 +0,0 @@
1 -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
2 -import 'package:cake_wallet/core/email_validator.dart';
3 -import 'package:cake_wallet/ionia/ionia_create_state.dart';
4 -import 'package:cake_wallet/routes.dart';
5 -import 'package:cake_wallet/src/screens/base_page.dart';
6 -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
7 -import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
8 -import 'package:cake_wallet/src/widgets/primary_button.dart';
9 -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
10 -import 'package:cake_wallet/typography.dart';
11 -import 'package:cake_wallet/utils/show_pop_up.dart';
12 -import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
13 -import 'package:flutter/gestures.dart';
14 -import 'package:flutter/material.dart';
15 -import 'package:cake_wallet/generated/i18n.dart';
16 -import 'package:flutter_mobx/flutter_mobx.dart';
17 -import 'package:mobx/mobx.dart';
18 -import 'package:url_launcher/url_launcher.dart';
19 -
20 -class IoniaCreateAccountPage extends BasePage {
21 - IoniaCreateAccountPage(this._authViewModel)
22 - : _emailFocus = FocusNode(),
23 - _emailController = TextEditingController(),
24 - _formKey = GlobalKey<FormState>() {
25 - _emailController.text = _authViewModel.email;
26 - _emailController.addListener(() => _authViewModel.email = _emailController.text);
27 - }
28 -
29 - final IoniaAuthViewModel _authViewModel;
30 -
31 - final GlobalKey<FormState> _formKey;
32 -
33 - final FocusNode _emailFocus;
34 - final TextEditingController _emailController;
35 -
36 - static const privacyPolicyUrl = 'https://ionia.docsend.com/view/jhjvdn7qq7k3ukwt';
37 - static const termsAndConditionsUrl = 'https://ionia.docsend.com/view/uceirymz2ijacq5g';
38 -
39 - @override
40 - Widget middle(BuildContext context) {
41 - return Text(
42 - S.current.sign_up,
43 - style: textMediumSemiBold(
44 - color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
45 - ),
46 - );
47 - }
48 -
49 - @override
50 - Widget body(BuildContext context) {
51 - reaction((_) => _authViewModel.createUserState, (IoniaCreateAccountState state) {
52 - if (state is IoniaCreateStateFailure) {
53 - _onCreateUserFailure(context, state.error);
54 - }
55 - if (state is IoniaCreateStateSuccess) {
56 - _onCreateSuccessful(context, _authViewModel);
57 - }
58 - });
59 -
60 - return ScrollableWithBottomSection(
61 - contentPadding: EdgeInsets.all(24),
62 - content: Form(
63 - key: _formKey,
64 - child: BaseTextFormField(
65 - hintText: S.of(context).email_address,
66 - focusNode: _emailFocus,
67 - validator: EmailValidator(),
68 - keyboardType: TextInputType.emailAddress,
69 - controller: _emailController,
70 - onSubmit: (_) => _createAccount(),
71 - ),
72 - ),
73 - bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24),
74 - bottomSection: Column(
75 - children: [
76 - Column(
77 - mainAxisAlignment: MainAxisAlignment.end,
78 - children: <Widget>[
79 - Observer(
80 - builder: (_) => LoadingPrimaryButton(
81 - text: S.of(context).create_account,
82 - onPressed: _createAccount,
83 - isLoading:
84 - _authViewModel.createUserState is IoniaCreateStateLoading,
85 - color: Theme.of(context).primaryColor,
86 - textColor: Colors.white,
87 - ),
88 - ),
89 - SizedBox(
90 - height: 20,
91 - ),
92 - RichText(
93 - textAlign: TextAlign.center,
94 - text: TextSpan(
95 - text: S.of(context).agree_to,
96 - style: TextStyle(
97 - color: Color(0xff7A93BA),
98 - fontSize: 12,
99 - fontFamily: 'Lato',
100 - ),
101 - children: [
102 - TextSpan(
103 - text: S.of(context).settings_terms_and_conditions,
104 - style: TextStyle(
105 - color: Theme.of(context).primaryColor,
106 - fontWeight: FontWeight.w700,
107 - ),
108 - recognizer: TapGestureRecognizer()
109 - ..onTap = () async {
110 - final uri = Uri.parse(termsAndConditionsUrl);
111 - if (await canLaunchUrl(uri))
112 - await launchUrl(uri, mode: LaunchMode.externalApplication);
113 - },
114 - ),
115 - TextSpan(text: ' ${S.of(context).and} '),
116 - TextSpan(
117 - text: S.of(context).privacy_policy,
118 - style: TextStyle(
119 - color: Theme.of(context).primaryColor,
120 - fontWeight: FontWeight.w700,
121 - ),
122 - recognizer: TapGestureRecognizer()
123 - ..onTap = () async {
124 - final uri = Uri.parse(privacyPolicyUrl);
125 - if (await canLaunchUrl(uri))
126 - await launchUrl(uri, mode: LaunchMode.externalApplication);
127 - }),
128 - TextSpan(text: ' ${S.of(context).by_cake_pay}'),
129 - ],
130 - ),
131 - ),
132 - ],
133 - ),
134 - ],
135 - ),
136 - );
137 - }
138 -
139 - void _onCreateUserFailure(BuildContext context, String error) {
140 - showPopUp<void>(
141 - context: context,
142 - builder: (BuildContext context) {
143 - return AlertWithOneAction(
144 - alertTitle: S.current.create_account,
145 - alertContent: error,
146 - buttonText: S.of(context).ok,
147 - buttonAction: () => Navigator.of(context).pop());
148 - });
149 - }
150 -
151 - void _onCreateSuccessful(BuildContext context, IoniaAuthViewModel authViewModel) => Navigator.pushNamed(
152 - context,
153 - Routes.ioniaVerifyIoniaOtpPage,
154 - arguments: [authViewModel.email, false],
155 - );
156 -
157 - void _createAccount() async {
158 - if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
159 - return;
160 - }
161 - await _authViewModel.createUser(_emailController.text);
162 - }
163 -}
lib/view_model/dashboard/dashboard_view_model.dart
+30 -20
@@ -48,6 +48,7 @@ import 'package:mobx/mobx.dart';
48 import 'package:cake_wallet/bitcoin/bitcoin.dart';
49 import 'package:http/http.dart' as http;
50 import 'package:shared_preferences/shared_preferences.dart';
51 +import 'package:cake_wallet/.secrets.g.dart' as secrets;
52
53 part 'dashboard_view_model.g.dart';
54
@@ -375,7 +376,8 @@ abstract class DashboardViewModelBase with Store {
376 .toList();
377 }
378
378 - bool get hasSellProviders => ProvidersHelper.getAvailableSellProviderTypes(wallet.type).isNotEmpty;
379 + bool get hasSellProviders =>
380 + ProvidersHelper.getAvailableSellProviderTypes(wallet.type).isNotEmpty;
381
382 bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
383
@@ -534,8 +536,11 @@ abstract class DashboardViewModelBase with Store {
536 void setSyncAll(bool value) => settingsStore.currentSyncAll = value;
537
538 Future<List<String>> checkForHavenWallets() async {
537 - final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
538 - return walletInfoSource.values.where((element) => element.type == WalletType.haven).map((e) => e.name).toList();
539 + final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
540 + return walletInfoSource.values
541 + .where((element) => element.type == WalletType.haven)
542 + .map((e) => e.name)
543 + .toList();
544 }
545
546 Future<List<String>> checkAffectedWallets() async {
@@ -576,29 +581,34 @@ abstract class DashboardViewModelBase with Store {
581 Future<ServicesResponse> getServicesStatus() async {
582 try {
583 if (isEnabledBulletinAction) {
579 - final res = await http.get(Uri.parse("https://service-api.cakewallet.com/v1/active-notices"));
584 + final uri = Uri.https(
585 + "service-api.cakewallet.com",
586 + "/v1/active-notices",
587 + {'key': secrets.fiatApiKey},
588 + );
589
581 - if (res.statusCode < 200 || res.statusCode >= 300) {
582 - throw res.body;
583 - }
590 + final res = await http.get(uri);
591 +
592 + if (res.statusCode < 200 || res.statusCode >= 300) {
593 + throw res.body;
594 + }
595
585 - final oldSha = sharedPreferences.getString(PreferencesKey.serviceStatusShaKey);
596 + final oldSha = sharedPreferences.getString(PreferencesKey.serviceStatusShaKey);
597
587 - final hash = await Cryptography.instance.sha256().hash(utf8.encode(res.body));
588 - final currentSha = bytesToHex(hash.bytes);
598 + final hash = await Cryptography.instance.sha256().hash(utf8.encode(res.body));
599 + final currentSha = bytesToHex(hash.bytes);
600
590 - final hasUpdates = oldSha != currentSha;
601 + final hasUpdates = oldSha != currentSha;
602
592 - return ServicesResponse.fromJson(
593 - json.decode(res.body) as Map<String, dynamic>,
594 - hasUpdates,
595 - currentSha,
596 - );
603 + return ServicesResponse.fromJson(
604 + json.decode(res.body) as Map<String, dynamic>,
605 + hasUpdates,
606 + currentSha,
607 + );
608 + } else {
609 + return ServicesResponse([], false, '');
610 }
598 - else {
599 - return ServicesResponse([], false, '');
600 - }
601 - } catch (_) {
611 + } catch (e) {
612 return ServicesResponse([], false, '');
613 }
614 }
lib/view_model/exchange/exchange_view_model.dart
+1 -1
@@ -508,7 +508,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
508 if (limitsState is LimitsLoadedSuccessfully) {
509 if (double.tryParse(amount) == null) continue;
510
511 - if (limits.max != null && double.parse(amount) < limits.min!)
511 + if (limits.min != null && double.parse(amount) < limits.min!)
512 continue;
513 else if (limits.max != null && double.parse(amount) > limits.max!)
514 continue;
macos/Flutter/GeneratedPluginRegistrant.swift
+2
@@ -10,6 +10,7 @@ import device_info_plus
10 import devicelocale
11 import flutter_inappwebview_macos
12 import flutter_local_authentication
13 +import flutter_secure_storage_macos
14 import in_app_review
15 import package_info
16 import package_info_plus
@@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
26 DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
27 InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
28 FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin"))
29 + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
30 InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
31 FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
32 FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
pubspec_base.yaml
+1
@@ -106,6 +106,7 @@ dependencies:
106 url: https://github.com/cake-tech/bitcoin_base
107 ref: cake-update-v3
108 ledger_flutter: ^1.0.1
109 + hashlib: 1.12.0
110
111 dev_dependencies:
112 flutter_test:
tool/generate_secrets_config.dart
-3
@@ -4,7 +4,6 @@ import 'utils/secret_key.dart';
4 import 'utils/utils.dart';
5
6 const baseConfigPath = 'tool/.secrets-config.json';
7 -const coreConfigPath = 'tool/.core-secrets-config.json';
7 const evmChainsConfigPath = 'tool/.evm-secrets-config.json';
8 const solanaConfigPath = 'tool/.solana-secrets-config.json';
9 const nanoConfigPath = 'tool/.nano-secrets-config.json';
@@ -38,7 +37,6 @@ Future<void> generateSecretsConfig(List<String> args) async {
37 });
38
39 final baseConfigFile = File(baseConfigPath);
41 - final coreConfigFile = File(coreConfigPath);
40 final evmChainsConfigFile = File(evmChainsConfigPath);
41 final solanaConfigFile = File(solanaConfigPath);
42 final nanoConfigFile = File(nanoConfigPath);
@@ -64,7 +62,6 @@ Future<void> generateSecretsConfig(List<String> args) async {
62
63 await writeConfig(baseConfigFile, SecretKey.base, existingSecrets: secrets);
64
67 - await writeConfig(coreConfigFile, SecretKey.coreSecrets);
65 await writeConfig(evmChainsConfigFile, SecretKey.evmChainsSecrets);
66 await writeConfig(solanaConfigFile, SecretKey.solanaSecrets);
67 await writeConfig(nanoConfigFile, SecretKey.nanoSecrets);
tool/utils/secret_key.dart
-2
@@ -45,8 +45,6 @@ class SecretKey {
45 SecretKey('authorization', () => ''),
46 ];
47
48 - static final coreSecrets = [];
49 -
48 static final evmChainsSecrets = [
49 SecretKey('etherScanApiKey', () => ''),
50 SecretKey('polygonScanApiKey', () => ''),