Merge pull request #875 from cypherstack/appConfig_julian

App config
This commit is contained in:
julian-CStack 2024-05-21 12:05:00 -06:00 committed by GitHub
commit 7550b334ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 627 additions and 561 deletions

View file

@ -1,9 +1,9 @@
abstract class AppConfig {
static String get appName => prefix + separator + suffix;
static const appName = prefix + _separator + suffix;
static String get prefix => "Stack";
static const prefix = "Stack";
static String get separator => " ";
static const _separator = " ";
static String get suffix => "Wallet";
static const suffix = "Wallet";
}

View file

@ -10,6 +10,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/app_config.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
@ -24,9 +25,9 @@ import 'package:tuple/tuple.dart';
class DesktopAttentionDeleteWallet extends ConsumerStatefulWidget {
const DesktopAttentionDeleteWallet({
Key? key,
super.key,
required this.walletId,
}) : super(key: key);
});
final String walletId;
@ -79,7 +80,7 @@ class _DesktopAttentionDeleteWallet
child: Text(
"You are going to permanently delete your wallet.\n\nIf you delete your wallet, "
"the only way you can have access to your funds is by using your backup key."
"\n\nStack Wallet does not keep nor is able to restore your backup key or your wallet."
"\n\n${AppConfig.appName} does not keep nor is able to restore your backup key or your wallet."
"\n\nPLEASE SAVE YOUR BACKUP KEY.",
style: STextStyles.desktopTextExtraExtraSmall(context)
.copyWith(
@ -118,7 +119,7 @@ class _DesktopAttentionDeleteWallet
if (wallet is MnemonicInterface) {
final words = await wallet.getMnemonicAsWords();
if (mounted) {
if (context.mounted) {
await Navigator.of(context).pushNamed(
DeleteWalletKeysPopup.routeName,
arguments: Tuple2(
@ -131,7 +132,7 @@ class _DesktopAttentionDeleteWallet
},
),
],
)
),
],
),
),

View file

@ -118,7 +118,7 @@ class _ForgottenPassphraseRestoreFromSWBState
final String? jsonString = await compute(
SWB.decryptStackWalletWithPassphrase,
Tuple2(fileToRestore, passphrase),
debugLabel: "stack wallet decryption compute",
debugLabel: "${AppConfig.appName} decryption compute",
);
if (mounted) {

View file

@ -14,6 +14,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/app_config.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/appearance_settings/sub_widgets/desktop_manage_themes.dart';
import 'package:stackwallet/providers/db/main_db_provider.dart';
@ -29,7 +30,7 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:tuple/tuple.dart';
class AppearanceOptionSettings extends ConsumerStatefulWidget {
const AppearanceOptionSettings({Key? key}) : super(key: key);
const AppearanceOptionSettings({super.key});
static const String routeName = "/settingsMenuAppearance";
@ -44,132 +45,139 @@ class _AppearanceOptionSettings
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
right: 30,
),
child: RoundedWhiteContainer(
radiusMultiplier: 2,
child: Wrap(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset(
Assets.svg.circleSun,
width: 48,
height: 48,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.all(10),
child: RichText(
textAlign: TextAlign.left,
text: TextSpan(
children: [
TextSpan(
text: "Appearances",
style: STextStyles.desktopTextSmall(context),
),
TextSpan(
text:
"\n\nCustomize how your Stack Wallet looks according to your preferences.",
style: STextStyles.desktopTextExtraExtraSmall(
context),
),
],
),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
right: 30,
),
child: RoundedWhiteContainer(
radiusMultiplier: 2,
child: Wrap(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset(
Assets.svg.circleSun,
width: 48,
height: 48,
),
],
),
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(
thickness: 0.5,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"Display favorite wallets",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark),
textAlign: TextAlign.left,
),
SizedBox(
height: 20,
width: 40,
child: DraggableSwitchButton(
isOn: ref.watch(
prefsChangeNotifierProvider.select(
(value) => value.showFavoriteWallets),
Padding(
padding: const EdgeInsets.all(10),
child: RichText(
textAlign: TextAlign.left,
text: TextSpan(
children: [
TextSpan(
text: "Appearances",
style:
STextStyles.desktopTextSmall(context),
),
TextSpan(
text:
"\n\nCustomize how your ${AppConfig.appName} looks according to your preferences.",
style:
STextStyles.desktopTextExtraExtraSmall(
context,
),
),
],
),
onValueChanged: (newValue) {
ref
.read(prefsChangeNotifierProvider)
.showFavoriteWallets = newValue;
},
),
)
],
),
),
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(
thickness: 0.5,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Choose theme",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark),
textAlign: TextAlign.left,
),
],
),
),
const Padding(
padding: EdgeInsets.all(2),
child: ThemeToggle(),
),
],
),
],
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(
thickness: 0.5,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Display favorite wallets",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
textAlign: TextAlign.left,
),
SizedBox(
height: 20,
width: 40,
child: DraggableSwitchButton(
isOn: ref.watch(
prefsChangeNotifierProvider.select(
(value) => value.showFavoriteWallets,
),
),
onValueChanged: (newValue) {
ref
.read(prefsChangeNotifierProvider)
.showFavoriteWallets = newValue;
},
),
),
],
),
),
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(
thickness: 0.5,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Choose theme",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
textAlign: TextAlign.left,
),
],
),
),
const Padding(
padding: EdgeInsets.all(2),
child: ThemeToggle(),
),
],
),
],
),
),
),
),
],
));
],
),
);
}
}
class ThemeToggle extends ConsumerStatefulWidget {
const ThemeToggle({
Key? key,
}) : super(key: key);
super.key,
});
@override
ConsumerState<ThemeToggle> createState() => _ThemeToggle();

View file

@ -13,6 +13,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:intl/intl.dart';
import 'package:stackwallet/app_config.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart';
@ -38,7 +39,7 @@ import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:url_launcher/url_launcher.dart';
class BackupRestoreSettings extends ConsumerStatefulWidget {
const BackupRestoreSettings({Key? key}) : super(key: key);
const BackupRestoreSettings({super.key});
static const String routeName = "/settingsMenuBackupRestore";
@ -299,7 +300,8 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
fileLocationController.text =
ref.read(prefsChangeNotifierProvider).autoBackupLocation ?? " ";
frequencyController.text = Format.prettyFrequencyType(
ref.read(prefsChangeNotifierProvider).backupFrequencyType);
ref.read(prefsChangeNotifierProvider).backupFrequencyType,
);
fileLocationFocusNode = FocusNode();
passwordFocusNode = FocusNode();
@ -324,8 +326,9 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
bool isEnabledAutoBackup = ref.watch(prefsChangeNotifierProvider
.select((value) => value.isAutoBackupEnabled));
final bool isEnabledAutoBackup = ref.watch(
prefsChangeNotifierProvider.select((value) => value.isAutoBackupEnabled),
);
ref.listen(
prefsChangeNotifierProvider
@ -334,8 +337,9 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
frequencyController.text = Format.prettyFrequencyType(next);
});
return LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
return LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ConstrainedBox(
constraints: BoxConstraints(
@ -386,23 +390,26 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
TextSpan(
text: "Auto Backup",
style: STextStyles.desktopTextSmall(
context),
context,
),
),
TextSpan(
text:
"\n\nAuto backup is a custom Stack Wallet feature that offers a convenient backup of your data."
"\n\nAuto backup is a custom ${AppConfig.appName} feature that offers a convenient backup of your data."
"To ensure maximum security, we recommend using a unique password that you haven't used anywhere "
"else on the internet before. Your password is not stored.",
style: STextStyles
.desktopTextExtraExtraSmall(
context),
context,
),
),
TextSpan(
text:
"\n\nFor more information, please see our website ",
style: STextStyles
.desktopTextExtraExtraSmall(
context),
context,
),
),
TextSpan(
text: "stackwallet.com",
@ -412,7 +419,8 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
..onTap = () {
launchUrl(
Uri.parse(
"https://stackwallet.com/"),
"https://stackwallet.com/",
),
mode: LaunchMode
.externalApplication,
);
@ -458,14 +466,16 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
"Backed up ${prettySinceLastBackupString(ref.watch(prefsChangeNotifierProvider.select((value) => value.lastAutoBackup)))}",
style:
STextStyles.itemSubtitle(
context),
context,
),
),
CustomTextButton(
text: "Back up now",
onTap: () {
ref
.read(
autoSWBServiceProvider)
autoSWBServiceProvider,
)
.doBackup();
},
),
@ -495,7 +505,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
},
),
],
)
),
],
),
),
@ -539,7 +549,8 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
TextSpan(
text: "Manual Backup",
style: STextStyles.desktopTextSmall(
context),
context,
),
),
TextSpan(
text:
@ -548,7 +559,8 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
"Use a strong password to encrypt your data.",
style: STextStyles
.desktopTextExtraExtraSmall(
context),
context,
),
),
],
),
@ -622,15 +634,17 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
TextSpan(
text: "Restore Backup",
style: STextStyles.desktopTextSmall(
context),
context,
),
),
TextSpan(
text:
"\n\nUse your Stack Wallet backup file to restore your wallets, address book "
"\n\nUse your ${AppConfig.appName} backup file to restore your wallets, address book "
"and wallet preferences.",
style: STextStyles
.desktopTextExtraExtraSmall(
context),
context,
),
),
],
),
@ -672,7 +686,9 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
],
),
),
));
});
),
);
},
);
}
}

View file

@ -43,7 +43,8 @@ Future<bool> doesCommitExist(
final Client client = Client();
try {
final uri = Uri.parse(
"$kGithubAPI$kGithubHead/$organization/$project/commits/$commit");
"$kGithubAPI$kGithubHead/$organization/$project/commits/$commit",
);
final commitQuery = await client.get(
uri,
@ -51,8 +52,10 @@ Future<bool> doesCommitExist(
);
final response = jsonDecode(commitQuery.body.toString());
Logging.instance.log("doesCommitExist $project $commit $response",
level: LogLevel.Info);
Logging.instance.log(
"doesCommitExist $project $commit $response",
level: LogLevel.Info,
);
bool isThereCommit;
try {
isThereCommit = response['sha'] == commit;
@ -78,7 +81,8 @@ Future<bool> isHeadCommit(
final Client client = Client();
try {
final uri = Uri.parse(
"$kGithubAPI$kGithubHead/$organization/$project/commits/$branch");
"$kGithubAPI$kGithubHead/$organization/$project/commits/$branch",
);
final commitQuery = await client.get(
uri,
@ -86,8 +90,10 @@ Future<bool> isHeadCommit(
);
final response = jsonDecode(commitQuery.body.toString());
Logging.instance.log("isHeadCommit $project $commit $branch $response",
level: LogLevel.Info);
Logging.instance.log(
"isHeadCommit $project $commit $branch $response",
level: LogLevel.Info,
);
bool isHead;
try {
isHead = response['sha'] == commit;
@ -103,31 +109,35 @@ Future<bool> isHeadCommit(
}
class DesktopAboutView extends ConsumerWidget {
const DesktopAboutView({Key? key}) : super(key: key);
const DesktopAboutView({super.key});
static const String routeName = "/desktopAboutView";
@override
Widget build(BuildContext context, WidgetRef ref) {
String firoCommit = FIRO_VERSIONS.getPluginVersion();
String epicCashCommit = EPIC_VERSIONS.getPluginVersion();
String moneroCommit = MONERO_VERSIONS.getPluginVersion();
List<Future> futureFiroList = [
final String firoCommit = FIRO_VERSIONS.getPluginVersion();
final String epicCashCommit = EPIC_VERSIONS.getPluginVersion();
final String moneroCommit = MONERO_VERSIONS.getPluginVersion();
final List<Future<bool>> futureFiroList = [
doesCommitExist("cypherstack", "flutter_liblelantus", firoCommit),
isHeadCommit("cypherstack", "flutter_liblelantus", "main", firoCommit),
];
Future commitFiroFuture = Future.wait(futureFiroList);
List<Future> futureEpicList = [
final Future<void> commitFiroFuture = Future.wait(futureFiroList);
final List<Future<bool>> futureEpicList = [
doesCommitExist("cypherstack", "flutter_libepiccash", epicCashCommit),
isHeadCommit(
"cypherstack", "flutter_libepiccash", "main", epicCashCommit),
"cypherstack",
"flutter_libepiccash",
"main",
epicCashCommit,
),
];
Future commitEpicFuture = Future.wait(futureEpicList);
List<Future> futureMoneroList = [
final Future<void> commitEpicFuture = Future.wait(futureEpicList);
final List<Future<bool>> futureMoneroList = [
doesCommitExist("cypherstack", "flutter_libmonero", moneroCommit),
isHeadCommit("cypherstack", "flutter_libmonero", "main", moneroCommit),
];
Future commitMoneroFuture = Future.wait(futureMoneroList);
final Future<void> commitMoneroFuture = Future.wait(futureMoneroList);
debugPrint("BUILD: $runtimeType");
return DesktopScaffold(
@ -143,7 +153,7 @@ class DesktopAboutView extends ConsumerWidget {
Text(
"About",
style: STextStyles.desktopH3(context),
)
),
],
),
),
@ -182,14 +192,15 @@ class DesktopAboutView extends ConsumerWidget {
children: [
TextSpan(
text:
"By using Stack Wallet, you agree to the ",
"By using ${AppConfig.appName}, you agree to the ",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
TextSpan(
text: "Terms of service",
@ -199,7 +210,8 @@ class DesktopAboutView extends ConsumerWidget {
..onTap = () {
launchUrl(
Uri.parse(
"https://stackwallet.com/terms-of-service.html"),
"https://stackwallet.com/terms-of-service.html",
),
mode:
LaunchMode.externalApplication,
);
@ -208,12 +220,13 @@ class DesktopAboutView extends ConsumerWidget {
TextSpan(
text: " and ",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
TextSpan(
text: "Privacy policy",
@ -223,7 +236,8 @@ class DesktopAboutView extends ConsumerWidget {
..onTap = () {
launchUrl(
Uri.parse(
"https://stackwallet.com/privacy-policy.html"),
"https://stackwallet.com/privacy-policy.html",
),
mode:
LaunchMode.externalApplication,
);
@ -242,8 +256,10 @@ class DesktopAboutView extends ConsumerWidget {
children: [
FutureBuilder(
future: PackageInfo.fromPlatform(),
builder: (context,
AsyncSnapshot<PackageInfo> snapshot) {
builder: (
context,
AsyncSnapshot<PackageInfo> snapshot,
) {
String version = "";
String signature = "";
String build = "";
@ -269,14 +285,16 @@ class DesktopAboutView extends ConsumerWidget {
Text(
"Version",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
),
const SizedBox(
height: 2,
@ -285,7 +303,8 @@ class DesktopAboutView extends ConsumerWidget {
version,
style:
STextStyles.itemSubtitle(
context),
context,
),
),
],
),
@ -299,14 +318,16 @@ class DesktopAboutView extends ConsumerWidget {
Text(
"Build number",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
),
const SizedBox(
height: 2,
@ -315,7 +336,8 @@ class DesktopAboutView extends ConsumerWidget {
build,
style:
STextStyles.itemSubtitle(
context),
context,
),
),
],
),
@ -331,14 +353,16 @@ class DesktopAboutView extends ConsumerWidget {
Text(
"Build signature",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
),
const SizedBox(
height: 2,
@ -347,7 +371,8 @@ class DesktopAboutView extends ConsumerWidget {
signature,
style:
STextStyles.itemSubtitle(
context),
context,
),
),
],
),
@ -355,316 +380,337 @@ class DesktopAboutView extends ConsumerWidget {
width: 350,
),
FutureBuilder(
future: commitFiroFuture,
builder: (context,
AsyncSnapshot<dynamic>
snapshot) {
bool commitExists = false;
bool isHead = false;
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
future: commitFiroFuture,
builder: (
context,
AsyncSnapshot<dynamic> snapshot,
) {
bool commitExists = false;
bool isHead = false;
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
if (snapshot.connectionState ==
ConnectionState
.done &&
snapshot.hasData) {
commitExists = snapshot
.data![0] as bool;
isHead = snapshot.data![1]
as bool;
if (commitExists &&
isHead) {
stateOfCommit =
CommitStatus.isHead;
} else if (commitExists) {
stateOfCommit =
CommitStatus
.isOldCommit;
} else {
stateOfCommit =
CommitStatus
.notACommit;
}
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
commitExists =
snapshot.data![0] as bool;
isHead =
snapshot.data![1] as bool;
if (commitExists && isHead) {
stateOfCommit =
CommitStatus.isHead;
} else if (commitExists) {
stateOfCommit = CommitStatus
.isOldCommit;
} else {
stateOfCommit =
CommitStatus.notACommit;
}
TextStyle indicationStyle =
STextStyles.itemSubtitle(
context);
switch (stateOfCommit) {
case CommitStatus.isHead:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorGreen);
break;
case CommitStatus
.isOldCommit:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorYellow);
break;
case CommitStatus
.notACommit:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorRed);
break;
default:
break;
}
return Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
"Firo Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark),
}
TextStyle indicationStyle =
STextStyles.itemSubtitle(
context,
);
switch (stateOfCommit) {
case CommitStatus.isHead:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorGreen,
);
break;
case CommitStatus.isOldCommit:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorYellow,
);
break;
case CommitStatus.notACommit:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorRed,
);
break;
default:
break;
}
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Firo Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
const SizedBox(
height: 2,
),
SelectableText(
firoCommit,
style: indicationStyle,
),
],
);
}),
),
const SizedBox(
height: 2,
),
SelectableText(
firoCommit,
style: indicationStyle,
),
],
);
},
),
],
),
const SizedBox(height: 35),
Row(
children: [
FutureBuilder(
future: commitEpicFuture,
builder: (context,
AsyncSnapshot<dynamic>
snapshot) {
bool commitExists = false;
bool isHead = false;
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
future: commitEpicFuture,
builder: (
context,
AsyncSnapshot<dynamic> snapshot,
) {
bool commitExists = false;
bool isHead = false;
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
if (snapshot.connectionState ==
ConnectionState
.done &&
snapshot.hasData) {
commitExists = snapshot
.data![0] as bool;
isHead = snapshot.data![1]
as bool;
if (commitExists &&
isHead) {
stateOfCommit =
CommitStatus.isHead;
} else if (commitExists) {
stateOfCommit =
CommitStatus
.isOldCommit;
} else {
stateOfCommit =
CommitStatus
.notACommit;
}
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
commitExists =
snapshot.data![0] as bool;
isHead =
snapshot.data![1] as bool;
if (commitExists && isHead) {
stateOfCommit =
CommitStatus.isHead;
} else if (commitExists) {
stateOfCommit = CommitStatus
.isOldCommit;
} else {
stateOfCommit =
CommitStatus.notACommit;
}
TextStyle indicationStyle =
STextStyles.itemSubtitle(
context);
switch (stateOfCommit) {
case CommitStatus.isHead:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorGreen);
break;
case CommitStatus
.isOldCommit:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorYellow);
break;
case CommitStatus
.notACommit:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorRed);
break;
default:
break;
}
return Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
"Epic Cash Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark),
}
TextStyle indicationStyle =
STextStyles.itemSubtitle(
context,
);
switch (stateOfCommit) {
case CommitStatus.isHead:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorGreen,
);
break;
case CommitStatus.isOldCommit:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorYellow,
);
break;
case CommitStatus.notACommit:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorRed,
);
break;
default:
break;
}
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Epic Cash Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
const SizedBox(
height: 2,
),
SelectableText(
epicCashCommit,
style: indicationStyle,
),
],
);
}),
),
const SizedBox(
height: 2,
),
SelectableText(
epicCashCommit,
style: indicationStyle,
),
],
);
},
),
const SizedBox(
width: 105,
),
FutureBuilder(
future: commitMoneroFuture,
builder: (context,
AsyncSnapshot<dynamic>
snapshot) {
bool commitExists = false;
bool isHead = false;
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
future: commitMoneroFuture,
builder: (
context,
AsyncSnapshot<dynamic> snapshot,
) {
bool commitExists = false;
bool isHead = false;
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
if (snapshot.connectionState ==
ConnectionState
.done &&
snapshot.hasData) {
commitExists = snapshot
.data![0] as bool;
isHead = snapshot.data![1]
as bool;
if (commitExists &&
isHead) {
stateOfCommit =
CommitStatus.isHead;
} else if (commitExists) {
stateOfCommit =
CommitStatus
.isOldCommit;
} else {
stateOfCommit =
CommitStatus
.notACommit;
}
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
commitExists =
snapshot.data![0] as bool;
isHead =
snapshot.data![1] as bool;
if (commitExists && isHead) {
stateOfCommit =
CommitStatus.isHead;
} else if (commitExists) {
stateOfCommit = CommitStatus
.isOldCommit;
} else {
stateOfCommit =
CommitStatus.notACommit;
}
TextStyle indicationStyle =
STextStyles.itemSubtitle(
context);
switch (stateOfCommit) {
case CommitStatus.isHead:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorGreen);
break;
case CommitStatus
.isOldCommit:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorYellow);
break;
case CommitStatus
.notACommit:
indicationStyle = STextStyles
.itemSubtitle(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.accentColorRed);
break;
default:
break;
}
return Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
"Monero Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark),
}
TextStyle indicationStyle =
STextStyles.itemSubtitle(
context,
);
switch (stateOfCommit) {
case CommitStatus.isHead:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorGreen,
);
break;
case CommitStatus.isOldCommit:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorYellow,
);
break;
case CommitStatus.notACommit:
indicationStyle =
STextStyles
.itemSubtitle(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.accentColorRed,
);
break;
default:
break;
}
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Monero Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
const SizedBox(
height: 2,
),
SelectableText(
moneroCommit,
style: indicationStyle,
),
],
);
}),
),
const SizedBox(
height: 2,
),
SelectableText(
moneroCommit,
style: indicationStyle,
),
],
);
},
),
],
),
const SizedBox(height: 35),
@ -673,20 +719,21 @@ class DesktopAboutView extends ConsumerWidget {
Text(
"Website:",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.textDark),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
),
CustomTextButton(
text: "https://stackwallet.com",
onTap: () {
launchUrl(
Uri.parse(
"https://stackwallet.com"),
"https://stackwallet.com",
),
mode: LaunchMode
.externalApplication,
);
@ -700,13 +747,13 @@ class DesktopAboutView extends ConsumerWidget {
Text(
"Tezos functionality:",
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.textDark),
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
),
CustomTextButton(
text: "Powered by TzKT API",
@ -723,10 +770,10 @@ class DesktopAboutView extends ConsumerWidget {
],
);
},
)
),
],
),
)
),
],
),
),

View file

@ -13,6 +13,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/app_config.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
@ -26,7 +27,7 @@ import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:zxcvbn/zxcvbn.dart';
class SecuritySettings extends ConsumerStatefulWidget {
const SecuritySettings({Key? key}) : super(key: key);
const SecuritySettings({super.key});
static const String routeName = "/settingsMenuSecurity";
@ -186,7 +187,7 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
height: 16,
),
Text(
"Protect your Stack Wallet with a strong password. Stack Wallet does not store "
"Protect your ${AppConfig.appName} with a strong password. ${AppConfig.appName} does not store "
"your password, and is therefore NOT able to restore it. Keep your password safe and secure.",
style: STextStyles.desktopTextExtraExtraSmall(context),
),

View file

@ -688,7 +688,7 @@ abstract class EthereumAPI {
try {
final response = await client.get(
url: Uri.parse(
"$stackBaseServer/abis?addrs=$contractAddress",
"$stackBaseServer/abis?addrs=$contractAddress&verbose=true",
),
proxyInfo: Prefs.instance.useTor
? TorService.sharedInstance.getProxyInfo()

View file

@ -16,7 +16,6 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/eth_commons.dart';
import 'package:stackwallet/utilities/extensions/extensions.dart';
import 'package:stackwallet/utilities/extensions/impl/contract_abi.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
@ -85,11 +84,17 @@ class EthTokenWallet extends Wallet {
final contractAddress =
web3dart.EthereumAddress.fromHex(tokenContract.address);
if (tokenContract.abi == null) {
// first try to update the abi regardless just in case something has changed
try {
_tokenContract = await _updateTokenABI(
forContract: tokenContract,
usingContractAddress: contractAddress.hex,
);
} catch (e, s) {
Logging.instance.log(
"$runtimeType _updateTokenABI(): $e\n$s",
level: LogLevel.Warning,
);
}
try {
@ -102,50 +107,36 @@ class EthTokenWallet extends Wallet {
contractAddress,
);
_sendFunction = _deployedContract.function('transfer');
// success
return;
} catch (_) {
// some failure so first try to make sure we have the latest abi
// continue
}
// Some failure, try for proxy contract
final contractAddressResponse =
await EthereumAPI.getProxyTokenImplementationAddress(
contractAddress.hex,
);
if (contractAddressResponse.value != null) {
_tokenContract = await _updateTokenABI(
forContract: tokenContract,
usingContractAddress: contractAddress.hex,
usingContractAddress: contractAddressResponse.value!,
);
try {
// try again to parse abi and extract transfer function
_deployedContract = web3dart.DeployedContract(
ContractAbiExtensions.fromJsonList(
jsonList: tokenContract.abi!,
name: tokenContract.name,
),
contractAddress,
);
_sendFunction = _deployedContract.function('transfer');
} catch (_) {
// if it fails again we check if there is a proxy token impl and
// then try one last time to update and parse the abi
final contractAddressResponse =
await EthereumAPI.getProxyTokenImplementationAddress(
contractAddress.hex);
if (contractAddressResponse.value != null) {
_tokenContract = await _updateTokenABI(
forContract: tokenContract,
usingContractAddress: contractAddressResponse.value!,
);
} else {
throw contractAddressResponse.exception!;
}
_deployedContract = web3dart.DeployedContract(
ContractAbiExtensions.fromJsonList(
jsonList: tokenContract.abi!,
name: tokenContract.name,
),
contractAddress,
);
_sendFunction = _deployedContract.function('transfer');
}
} else {
throw contractAddressResponse.exception!;
}
_deployedContract = web3dart.DeployedContract(
ContractAbiExtensions.fromJsonList(
jsonList: tokenContract.abi!,
name: tokenContract.name,
),
contractAddress,
);
_sendFunction = _deployedContract.function('transfer');
} catch (e, s) {
Logging.instance.log(
"$runtimeType wallet failed init(): $e\n$s",
@ -181,8 +172,10 @@ class EthTokenWallet extends Wallet {
final myWeb3Address = web3dart.EthereumAddress.fromHex(myAddress);
final nonce = txData.nonce ??
await client.getTransactionCount(myWeb3Address,
atBlock: const web3dart.BlockNum.pending());
await client.getTransactionCount(
myWeb3Address,
atBlock: const web3dart.BlockNum.pending(),
);
final amount = txData.recipients!.first.amount;
final address = txData.recipients!.first.address;
@ -408,7 +401,7 @@ class EthTokenWallet extends Wallet {
final List<OutputV2> outputs = [];
final List<InputV2> inputs = [];
OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor(
final output = OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: "00",
valueStringSats: amount.raw.toString(),
addresses: [
@ -416,7 +409,7 @@ class EthTokenWallet extends Wallet {
],
walletOwns: addressTo == addressString,
);
InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor(
final input = InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: null,
scriptSigAsm: null,
sequence: null,