easy or more private option added at startup

This commit is contained in:
Marco 2022-10-09 21:36:43 -06:00
parent 3e8e2903f7
commit 4339c19631
12 changed files with 291 additions and 22 deletions

View file

@ -0,0 +1 @@
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg"><circle cx="500" cy="500" fill="#3030d0" r="432"/><path d="m442.46 592.28-.57 268.21 198.9-5.86 11.38-321.78z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="m442.09 765.51 203.95-59.38 6.13-173.28-209.71 59.43z" opacity=".22"/><path d="m299.56 684.62s-8.22-210.92 8.29-329.62c8.89-63.9 6.27-86.42 58.8-92.57 52.53-6.16 222.73-16.46 273.84-16.36s77.74 48.91 70.71 85.32c-7.03 36.4-88.37 376.37-88.37 376.37l-301.28 5.73s-18.98.58-21.98-28.86z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="m416.46 801.5v70.09l245.8-2.47 5.5-66.78c1.19-14.45-9.89-26.63-23.33-25.65-29.56 2.17-77.95 5.24-108.03 4.68-30.37-.57-73.34-1.57-98.76-2.18-11.62-.28-21.18 9.79-21.18 22.31z"/><path d="m212.11 1000s22.98-177.76 322.9-169.37 367.93 169.37 367.93 169.37z"/><path d="m640.48 246.07c-24.39-.05-75.9 2.27-128.79 5.38 11.79 5.42 37.9 15.11 56.38 16.52 30.63 2.34 58.35 12.55 62.75 53.5 4.92 45.8-4.27 142.61 48.4 148.92 15.72-66.74 29.29-125.09 31.98-139.01 7.03-36.4-19.6-85.21-70.71-85.32z" fill="#737577"/><path d="m374.41 456.19s1 44.15-22.69 63.11-30.98 32.54-22.93 53.72c8.27 21.75 65.71 28.98 66.07-15.06" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="m373.02 452.24 36.19-1.69" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/><path d="m537.85 454.95 145.93-5.41" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/><circle cx="307.82" cy="449.54" fill="none" r="64.32" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/><circle cx="473.53" cy="450.55" fill="none" r="64.32" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/><path d="m364.36 646.64c2.67-.29 54.2 9.08 59.48-10.41" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="m321.83 450.13c-1.12 10.47 2.47 28.19 15.33 27.24s18.88-14.37 19.08-27.24-3.26-23.84-15.13-23.84-17.81 9.98-19.29 23.84z"/><path d="m504.71 453.56c1.12-10.47-2.47-28.19-15.33-27.24s-18.88 14.37-19.08 27.24 3.26 23.84 15.13 23.84 17.81-9.98 19.29-23.84z"/><g stroke-linecap="round" stroke-linejoin="round"><path d="m512.3 368.41-57.19 1.59" fill="none" stroke="#000" stroke-width="3"/><path d="m349.98 367.85h-42.16" fill="none" stroke="#000" stroke-width="3"/><path d="m436.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m456.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m476.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m496.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m606.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m626.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m646.62 797.73v49.55" fill="none" stroke="#737577" stroke-width="3"/><path d="m299.56 684.62s-8.22-210.92 8.29-329.62c8.89-63.9 6.27-86.42 58.8-92.57 52.53-6.16 222.73-16.46 273.84-16.36s77.74 48.91 70.71 85.32c-7.03 36.4-88.37 376.37-88.37 376.37l-301.28 5.73s-18.98.58-21.98-28.86z" fill="none" stroke="#000" stroke-width="3"/><path d="m511.69 251.45s-37.95-15.01-57.83-50.66-68.35-27.46-87.75-13.63-34.85 32.58-24.99 61.63c10.76 31.71 57.41 38.43 101.33 20.24s37.13-15.61 37.13-15.61z" fill="#737577" stroke="#000" stroke-width="3"/></g><path d="m640.62 556.81c-.42 40.78 1.06 71.9 1.06 71.9l15.01-63.14-16.08-8.76z" opacity=".22"/><path d="m657.01 461.55s5.39-27.35 26.77-25.44c21.37 1.91 25.82 15.62 26.27 21.99s-10.85 81.79-16.87 112.22c-1.78 9.02-12.6 19.12-28.76 17.53-12.39-1.22-26.41-11.7-23.93-29.01" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="m387.22 602.43c-11.56 2.17 4.45 17.83 11.14 17.83h63.23s-42.63-23.78-74.36-17.83z" fill="#737577"/><path d="m374.54 602.43c11.56 2.17-4.45 17.83-11.14 17.83h-63.23s42.63-23.78 74.36-17.83z" fill="#737577"/><path d="m0 0v1000h1000v-1000zm500 932c-238.59 0-432-193.41-432-432s193.41-432 432-432 432 193.41 432 432-193.41 432-432 432z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -21,6 +21,10 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/utilities/logger.dart';
class HomeView extends ConsumerStatefulWidget { class HomeView extends ConsumerStatefulWidget {
const HomeView({Key? key}) : super(key: key); const HomeView({Key? key}) : super(key: key);
@ -81,7 +85,15 @@ class _HomeViewState extends ConsumerState<HomeView> {
void _loadCNData() { void _loadCNData() {
// unawaited future // unawaited future
//
final externalCalls = DB.instance
.get<dynamic>(boxName: DB.boxNamePrefs, key: "externalCalls") as bool?;
if (externalCalls ?? false) {
_cnLoadingService.loadAll(ref); _cnLoadingService.loadAll(ref);
} else {
Logging.instance.log("User does not want to use external calls",
level: LogLevel.Info);
}
} }
@override @override

View file

@ -15,6 +15,9 @@ import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/services/change_now/change_now_loading_service.dart';
class HomeViewButtonBar extends ConsumerStatefulWidget { class HomeViewButtonBar extends ConsumerStatefulWidget {
const HomeViewButtonBar({Key? key}) : super(key: key); const HomeViewButtonBar({Key? key}) : super(key: key);
@ -207,7 +210,14 @@ class _HomeViewButtonBarState extends ConsumerState<HomeViewButtonBar> {
ref.read(homeViewPageIndexStateProvider.state).state = 1; ref.read(homeViewPageIndexStateProvider.state).state = 1;
} }
DateTime now = DateTime.now(); DateTime now = DateTime.now();
// TODO: find out why it infinitely loads
final _cnLoadingService = ChangeNowLoadingService();
final externalCalls = DB.instance.get<dynamic>(
boxName: DB.boxNamePrefs, key: "externalCalls") as bool?;
if (!(externalCalls ?? false)) {
print("loading?");
unawaited(_cnLoadingService.loadAll(ref));
}
if (now.difference(_lastRefreshed) > _refreshInterval) { if (now.difference(_lastRefreshed) > _refreshInterval) {
// bool okPressed = false; // bool okPressed = false;
// showDialog<dynamic>( // showDialog<dynamic>(

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
@ -9,6 +11,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/utilities/util.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:stackwallet/hive/db.dart';
class IntroView extends StatefulWidget { class IntroView extends StatefulWidget {
const IntroView({Key? key}) : super(key: key); const IntroView({Key? key}) : super(key: key);
@ -240,7 +244,9 @@ class GetStartedButton extends StatelessWidget {
.extension<StackColors>()! .extension<StackColors>()!
.getPrimaryEnabledButtonColor(context), .getPrimaryEnabledButtonColor(context),
onPressed: () { onPressed: () {
Navigator.of(context).pushNamed(CreatePinView.routeName); unawaited(DB.instance.put<dynamic>(
boxName: DB.boxNamePrefs, key: "externalCalls", value: true));
Navigator.of(context).pushNamed(StackPrivacyCalls.routeName);
}, },
child: Text( child: Text(
"Get started", "Get started",

View file

@ -1,10 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/pinpad_views/create_pin_view.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/util.dart';
class StackPrivacyCalls extends ConsumerStatefulWidget { class StackPrivacyCalls extends ConsumerStatefulWidget {
const StackPrivacyCalls({ const StackPrivacyCalls({
Key? key, Key? key,
@ -17,9 +23,17 @@ class StackPrivacyCalls extends ConsumerStatefulWidget {
} }
class _StackPrivacyCalls extends ConsumerState<StackPrivacyCalls> { class _StackPrivacyCalls extends ConsumerState<StackPrivacyCalls> {
late final bool isDesktop;
bool isEasy = true;
final PageController _pageController = final PageController _pageController =
PageController(initialPage: 0, keepPage: true); PageController(initialPage: 0, keepPage: true);
@override
void initState() {
isDesktop = Util.isDesktop;
super.initState();
}
@override @override
void dispose() { void dispose() {
_pageController.dispose(); _pageController.dispose();
@ -59,6 +73,21 @@ class _StackPrivacyCalls extends ConsumerState<StackPrivacyCalls> {
const SizedBox( const SizedBox(
height: 36, height: 36,
), ),
Center(
child: CustomRadio((bool isEasy) {
setState(() {
this.isEasy = isEasy;
DB.instance.put<dynamic>(
boxName: DB.boxNamePrefs,
key: "externalCalls",
value: isEasy);
});
}),
),
const SizedBox(
height: 36,
),
RoundedWhiteContainer( RoundedWhiteContainer(
child: Center( child: Center(
child: RichText( child: RichText(
@ -66,22 +95,55 @@ class _StackPrivacyCalls extends ConsumerState<StackPrivacyCalls> {
text: TextSpan( text: TextSpan(
style: style:
STextStyles.label(context).copyWith(fontSize: 12.0), STextStyles.label(context).copyWith(fontSize: 12.0),
children: [ children: isEasy
const TextSpan( ? const [
TextSpan(
text: text:
"Exchange data preloaded for a seamless experience."), "Exchange data preloaded for a seamless experience."),
const TextSpan(
text:
"CoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."),
TextSpan( TextSpan(
text: "Recommended for most crypto users.", text:
"\n\nCoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."),
TextSpan(
text:
"\n\nRecommended for most crypto users.",
style: style:
const TextStyle(fontWeight: FontWeight.bold)), TextStyle(fontWeight: FontWeight.bold)),
]
: const [
TextSpan(
text:
"Exchange data not preloaded (slower experience)."),
TextSpan(
text:
"\n\nCoinGecko disabled (price changes not shown, no wallet value shown in other currencies)."),
TextSpan(
text:
"\n\nRecommended for the privacy conscious.",
style:
TextStyle(fontWeight: FontWeight.bold)),
], ],
), ),
), ),
), ),
), ),
const Spacer(
flex: 4,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
),
child: Row(
children: [
Expanded(
child: ContinueButton(
isDesktop: isDesktop,
),
),
],
),
),
], ],
), ),
], ],
@ -90,3 +152,149 @@ class _StackPrivacyCalls extends ConsumerState<StackPrivacyCalls> {
); );
} }
} }
class ContinueButton extends StatelessWidget {
const ContinueButton({Key? key, required this.isDesktop}) : super(key: key);
final bool isDesktop;
@override
Widget build(BuildContext context) {
return !isDesktop
? TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
onPressed: () {
Navigator.of(context).pushNamed(CreatePinView.routeName);
},
child: Text(
"Continue",
style: STextStyles.button(context),
),
)
: SizedBox(
width: 328,
height: 70,
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
onPressed: () {
Navigator.of(context).pushNamed(StackPrivacyCalls.routeName);
},
child: Text(
"Continue",
style: STextStyles.button(context).copyWith(fontSize: 20),
),
),
);
}
}
class CustomRadio extends StatefulWidget {
CustomRadio(this.upperCall, {Key? key}) : super(key: key);
Function upperCall;
@override
createState() {
return CustomRadioState();
}
}
class CustomRadioState extends State<CustomRadio> {
List<RadioModel> sampleData = <RadioModel>[];
@override
void initState() {
super.initState();
sampleData.add(
RadioModel(true, Assets.svg.personaEasy, 'Easy Crypto', 'Recommended'));
sampleData.add(RadioModel(
false, Assets.svg.personaIncognito, 'Incognito', 'Privacy conscious'));
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () {
setState(() {
// if (!sampleData[0].isSelected) {
widget.upperCall.call(true);
// }
for (var element in sampleData) {
element.isSelected = false;
}
sampleData[0].isSelected = true;
});
},
child: RadioItem(sampleData[0]),
),
InkWell(
onTap: () {
setState(() {
// if (!sampleData[1].isSelected) {
widget.upperCall.call(false);
// }
for (var element in sampleData) {
element.isSelected = false;
}
sampleData[1].isSelected = true;
});
},
child: RadioItem(sampleData[1]),
)
],
);
}
}
class RadioItem extends StatelessWidget {
final RadioModel _item;
const RadioItem(this._item, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(15.0),
child: RoundedWhiteContainer(
borderColor: _item.isSelected ? const Color(0xFF0056D2) : null,
child: Center(
child: Column(
children: [
SvgPicture.asset(
_item.svg,
// color: Theme.of(context).extension<StackColors>()!.textWhite,
width: 96,
height: 96,
),
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: STextStyles.label(context).copyWith(fontSize: 12.0),
children: [
TextSpan(
text: _item.topText,
style: const TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: "\n${_item.bottomText}"),
],
),
),
],
)),
),
);
}
}
class RadioModel {
bool isSelected;
final String svg;
final String topText;
final String bottomText;
RadioModel(this.isSelected, this.svg, this.topText, this.bottomText);
}

View file

@ -46,6 +46,10 @@ import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/utilities/logger.dart';
/// [eventBus] should only be set during testing /// [eventBus] should only be set during testing
class WalletView extends ConsumerStatefulWidget { class WalletView extends ConsumerStatefulWidget {
const WalletView({ const WalletView({
@ -351,7 +355,14 @@ class _WalletViewState extends ConsumerState<WalletView> {
void _loadCNData() { void _loadCNData() {
// unawaited future // unawaited future
final externalCalls = DB.instance
.get<dynamic>(boxName: DB.boxNamePrefs, key: "externalCalls") as bool?;
if (externalCalls ?? false) {
_cnLoadingService.loadAll(ref, coin: ref.read(managerProvider).coin); _cnLoadingService.loadAll(ref, coin: ref.read(managerProvider).coin);
} else {
Logging.instance.log("User does not want to use external calls",
level: LogLevel.Info);
}
} }
@override @override

View file

@ -76,6 +76,14 @@ class PriceAPI {
return _cachedPrices; return _cachedPrices;
} }
final externalCalls = DB.instance
.get<dynamic>(boxName: DB.boxNamePrefs, key: "externalCalls") as bool?;
if (!(externalCalls ?? false)) {
Logging.instance.log("User does not want to use external calls",
level: LogLevel.Info);
return _cachedPrices;
}
Map<Coin, Tuple2<Decimal, double>> result = {}; Map<Coin, Tuple2<Decimal, double>> result = {};
try { try {
final uri = Uri.parse( final uri = Uri.parse(
@ -88,14 +96,8 @@ class PriceAPI {
headers: {'Content-Type': 'application/json'}, headers: {'Content-Type': 'application/json'},
); );
// debugPrint(coinGeckoResponse.statusCode.toString());
// debugPrint(coinGeckoResponse.body.toString());
// debugPrint(coinGeckoResponse.headers.toString());
final coinGeckoData = jsonDecode(coinGeckoResponse.body) as List<dynamic>; final coinGeckoData = jsonDecode(coinGeckoResponse.body) as List<dynamic>;
// log(JsonEncoder.withIndent(" ").convert(coinGeckoData));
for (final map in coinGeckoData) { for (final map in coinGeckoData) {
final String coinName = map["name"] as String; final String coinName = map["name"] as String;
final coin = coinFromPrettyName(coinName); final coin = coinFromPrettyName(coinName);
@ -120,6 +122,14 @@ class PriceAPI {
} }
static Future<List<String>?> availableBaseCurrencies() async { static Future<List<String>?> availableBaseCurrencies() async {
final externalCalls = DB.instance
.get<dynamic>(boxName: DB.boxNamePrefs, key: "externalCalls") as bool?;
print("externalCalls hi2 $externalCalls");
if (!(externalCalls ?? false)) {
Logging.instance.log("User does not want to use external calls",
level: LogLevel.Info);
return null;
}
const uriString = const uriString =
"https://api.coingecko.com/api/v3/simple/supported_vs_currencies"; "https://api.coingecko.com/api/v3/simple/supported_vs_currencies";
try { try {

View file

@ -52,6 +52,8 @@ class _SVG {
"assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/tx-exchange-icon-failed.svg"; "assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/tx-exchange-icon-failed.svg";
String get polygon => "assets/svg/Polygon.svg"; String get polygon => "assets/svg/Polygon.svg";
String get personaIncognito => "assets/svg/persona-incognito-1.svg";
String get personaEasy => "assets/svg/persona-easy-1.svg";
String get drd => "assets/svg/drd-icon.svg"; String get drd => "assets/svg/drd-icon.svg";
String get boxAuto => "assets/svg/box-auto.svg"; String get boxAuto => "assets/svg/box-auto.svg";
String get plus => "assets/svg/plus.svg"; String get plus => "assets/svg/plus.svg";

View file

@ -10,6 +10,7 @@ class RoundedContainer extends StatelessWidget {
this.radiusMultiplier = 1.0, this.radiusMultiplier = 1.0,
this.width, this.width,
this.height, this.height,
this.borderColor,
}) : super(key: key); }) : super(key: key);
final Widget? child; final Widget? child;
@ -18,6 +19,7 @@ class RoundedContainer extends StatelessWidget {
final double radiusMultiplier; final double radiusMultiplier;
final double? width; final double? width;
final double? height; final double? height;
final Color? borderColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -29,6 +31,7 @@ class RoundedContainer extends StatelessWidget {
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius * radiusMultiplier, Constants.size.circularBorderRadius * radiusMultiplier,
), ),
border: borderColor == null ? null : Border.all(color: borderColor!),
), ),
child: Padding( child: Padding(
padding: padding, padding: padding,

View file

@ -10,6 +10,7 @@ class RoundedWhiteContainer extends StatelessWidget {
this.radiusMultiplier = 1.0, this.radiusMultiplier = 1.0,
this.width, this.width,
this.height, this.height,
this.borderColor,
}) : super(key: key); }) : super(key: key);
final Widget? child; final Widget? child;
@ -17,6 +18,7 @@ class RoundedWhiteContainer extends StatelessWidget {
final double radiusMultiplier; final double radiusMultiplier;
final double? width; final double? width;
final double? height; final double? height;
final Color? borderColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -27,6 +29,7 @@ class RoundedWhiteContainer extends StatelessWidget {
width: width, width: width,
height: height, height: height,
child: child, child: child,
borderColor: borderColor,
); );
} }
} }

View file

@ -290,6 +290,8 @@ flutter:
- assets/svg/tx-icon-anonymize-pending.svg - assets/svg/tx-icon-anonymize-pending.svg
- assets/svg/tx-icon-anonymize-failed.svg - assets/svg/tx-icon-anonymize-failed.svg
- assets/svg/Polygon.svg - assets/svg/Polygon.svg
- assets/svg/persona-easy-1.svg
- assets/svg/persona-incognito-1.svg
# coin icons # coin icons
- assets/svg/coin_icons/Bitcoin.svg - assets/svg/coin_icons/Bitcoin.svg
- assets/svg/coin_icons/Bitcoincash.svg - assets/svg/coin_icons/Bitcoincash.svg