diff --git a/assets/svg/fruitSorbet/bitcoin.svg b/assets/images/dark/bitcoin.svg
similarity index 100%
rename from assets/svg/fruitSorbet/bitcoin.svg
rename to assets/images/dark/bitcoin.svg
diff --git a/assets/svg/fruitSorbet/bitcoincash.svg b/assets/images/dark/bitcoincash.svg
similarity index 100%
rename from assets/svg/fruitSorbet/bitcoincash.svg
rename to assets/images/dark/bitcoincash.svg
diff --git a/assets/svg/fruitSorbet/doge.svg b/assets/images/dark/doge.svg
similarity index 100%
rename from assets/svg/fruitSorbet/doge.svg
rename to assets/images/dark/doge.svg
diff --git a/assets/svg/fruitSorbet/firo.svg b/assets/images/dark/firo.svg
similarity index 100%
rename from assets/svg/fruitSorbet/firo.svg
rename to assets/images/dark/firo.svg
diff --git a/assets/images/dark/litecoin.svg b/assets/images/dark/litecoin.svg
new file mode 100644
index 000000000..f224c429f
--- /dev/null
+++ b/assets/images/dark/litecoin.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/svg/fruitSorbet/particl.svg b/assets/images/dark/particl.svg
similarity index 100%
rename from assets/svg/fruitSorbet/particl.svg
rename to assets/images/dark/particl.svg
diff --git a/assets/images/dark/stack.svg b/assets/images/dark/stack.svg
new file mode 100644
index 000000000..43f29e515
--- /dev/null
+++ b/assets/images/dark/stack.svg
@@ -0,0 +1,440 @@
+
diff --git a/assets/svg/fruitSorbet/wownero.svg b/assets/images/dark/wownero.svg
similarity index 100%
rename from assets/svg/fruitSorbet/wownero.svg
rename to assets/images/dark/wownero.svg
diff --git a/assets/images/forest/bitcoin.svg b/assets/images/forest/bitcoin.svg
new file mode 100644
index 000000000..11b4e0b1e
--- /dev/null
+++ b/assets/images/forest/bitcoin.svg
@@ -0,0 +1,127 @@
+
diff --git a/assets/images/forest/bitcoincash.svg b/assets/images/forest/bitcoincash.svg
new file mode 100644
index 000000000..fec0dcfe1
--- /dev/null
+++ b/assets/images/forest/bitcoincash.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/images/forest/doge.svg b/assets/images/forest/doge.svg
new file mode 100644
index 000000000..2c1d693b4
--- /dev/null
+++ b/assets/images/forest/doge.svg
@@ -0,0 +1,255 @@
+
diff --git a/assets/images/forest/epic.png b/assets/images/forest/epic.png
deleted file mode 100644
index 75b75c267..000000000
Binary files a/assets/images/forest/epic.png and /dev/null differ
diff --git a/assets/images/forest/firo.svg b/assets/images/forest/firo.svg
new file mode 100644
index 000000000..d1bddcd74
--- /dev/null
+++ b/assets/images/forest/firo.svg
@@ -0,0 +1,126 @@
+
diff --git a/assets/images/forest/litecoin.svg b/assets/images/forest/litecoin.svg
new file mode 100644
index 000000000..f224c429f
--- /dev/null
+++ b/assets/images/forest/litecoin.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/images/forest/particl.svg b/assets/images/forest/particl.svg
new file mode 100644
index 000000000..0084fa615
--- /dev/null
+++ b/assets/images/forest/particl.svg
@@ -0,0 +1,283 @@
+
diff --git a/assets/images/forest/stack.svg b/assets/images/forest/stack.svg
new file mode 100644
index 000000000..cbb754036
--- /dev/null
+++ b/assets/images/forest/stack.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/images/forest/wownero.svg b/assets/images/forest/wownero.svg
new file mode 100644
index 000000000..7bcf97568
--- /dev/null
+++ b/assets/images/forest/wownero.svg
@@ -0,0 +1,220 @@
+
diff --git a/assets/images/fruitSorbet/bitcoin.svg b/assets/images/fruitSorbet/bitcoin.svg
new file mode 100644
index 000000000..d3abd0954
--- /dev/null
+++ b/assets/images/fruitSorbet/bitcoin.svg
@@ -0,0 +1,84 @@
+
diff --git a/assets/images/fruitSorbet/bitcoincash.svg b/assets/images/fruitSorbet/bitcoincash.svg
new file mode 100644
index 000000000..6a10cce09
--- /dev/null
+++ b/assets/images/fruitSorbet/bitcoincash.svg
@@ -0,0 +1,118 @@
+
diff --git a/assets/images/fruitSorbet/doge.svg b/assets/images/fruitSorbet/doge.svg
new file mode 100644
index 000000000..2c1d693b4
--- /dev/null
+++ b/assets/images/fruitSorbet/doge.svg
@@ -0,0 +1,255 @@
+
diff --git a/assets/images/fruitSorbet/firo.svg b/assets/images/fruitSorbet/firo.svg
new file mode 100644
index 000000000..6f502205c
--- /dev/null
+++ b/assets/images/fruitSorbet/firo.svg
@@ -0,0 +1,198 @@
+
diff --git a/assets/images/fruitSorbet/litecoin.svg b/assets/images/fruitSorbet/litecoin.svg
new file mode 100644
index 000000000..f224c429f
--- /dev/null
+++ b/assets/images/fruitSorbet/litecoin.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/images/fruitSorbet/particl.svg b/assets/images/fruitSorbet/particl.svg
new file mode 100644
index 000000000..d15918985
--- /dev/null
+++ b/assets/images/fruitSorbet/particl.svg
@@ -0,0 +1,188 @@
+
diff --git a/assets/images/fruitSorbet/stack.svg b/assets/images/fruitSorbet/stack.svg
new file mode 100644
index 000000000..cedb7e1d5
--- /dev/null
+++ b/assets/images/fruitSorbet/stack.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/images/fruitSorbet/wownero.svg b/assets/images/fruitSorbet/wownero.svg
new file mode 100644
index 000000000..812123542
--- /dev/null
+++ b/assets/images/fruitSorbet/wownero.svg
@@ -0,0 +1,190 @@
+
diff --git a/assets/images/light/bitcoin.svg b/assets/images/light/bitcoin.svg
new file mode 100644
index 000000000..d3abd0954
--- /dev/null
+++ b/assets/images/light/bitcoin.svg
@@ -0,0 +1,84 @@
+
diff --git a/assets/images/light/bitcoincash.svg b/assets/images/light/bitcoincash.svg
new file mode 100644
index 000000000..6a10cce09
--- /dev/null
+++ b/assets/images/light/bitcoincash.svg
@@ -0,0 +1,118 @@
+
diff --git a/assets/images/light/doge.svg b/assets/images/light/doge.svg
new file mode 100644
index 000000000..2c1d693b4
--- /dev/null
+++ b/assets/images/light/doge.svg
@@ -0,0 +1,255 @@
+
diff --git a/assets/images/light/firo.svg b/assets/images/light/firo.svg
new file mode 100644
index 000000000..6f502205c
--- /dev/null
+++ b/assets/images/light/firo.svg
@@ -0,0 +1,198 @@
+
diff --git a/assets/images/light/litecoin.svg b/assets/images/light/litecoin.svg
new file mode 100644
index 000000000..f224c429f
--- /dev/null
+++ b/assets/images/light/litecoin.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/images/light/particl.svg b/assets/images/light/particl.svg
new file mode 100644
index 000000000..d15918985
--- /dev/null
+++ b/assets/images/light/particl.svg
@@ -0,0 +1,188 @@
+
diff --git a/assets/images/light/stack.svg b/assets/images/light/stack.svg
new file mode 100644
index 000000000..43f29e515
--- /dev/null
+++ b/assets/images/light/stack.svg
@@ -0,0 +1,440 @@
+
diff --git a/assets/images/light/wownero.svg b/assets/images/light/wownero.svg
new file mode 100644
index 000000000..812123542
--- /dev/null
+++ b/assets/images/light/wownero.svg
@@ -0,0 +1,190 @@
+
diff --git a/assets/images/oceanBreeze/bitcoin.svg b/assets/images/oceanBreeze/bitcoin.svg
new file mode 100644
index 000000000..d3abd0954
--- /dev/null
+++ b/assets/images/oceanBreeze/bitcoin.svg
@@ -0,0 +1,84 @@
+
diff --git a/assets/images/oceanBreeze/bitcoincash.svg b/assets/images/oceanBreeze/bitcoincash.svg
new file mode 100644
index 000000000..6a10cce09
--- /dev/null
+++ b/assets/images/oceanBreeze/bitcoincash.svg
@@ -0,0 +1,118 @@
+
diff --git a/assets/images/oceanBreeze/doge.svg b/assets/images/oceanBreeze/doge.svg
new file mode 100644
index 000000000..2c1d693b4
--- /dev/null
+++ b/assets/images/oceanBreeze/doge.svg
@@ -0,0 +1,255 @@
+
diff --git a/assets/images/oceanBreeze/firo.svg b/assets/images/oceanBreeze/firo.svg
new file mode 100644
index 000000000..6f502205c
--- /dev/null
+++ b/assets/images/oceanBreeze/firo.svg
@@ -0,0 +1,198 @@
+
diff --git a/assets/images/oceanBreeze/litecoin.svg b/assets/images/oceanBreeze/litecoin.svg
new file mode 100644
index 000000000..f224c429f
--- /dev/null
+++ b/assets/images/oceanBreeze/litecoin.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/images/oceanBreeze/particl.svg b/assets/images/oceanBreeze/particl.svg
new file mode 100644
index 000000000..d15918985
--- /dev/null
+++ b/assets/images/oceanBreeze/particl.svg
@@ -0,0 +1,188 @@
+
diff --git a/assets/images/oceanBreeze/stack.png b/assets/images/oceanBreeze/stack.png
index b59af1608..317c9f775 100644
Binary files a/assets/images/oceanBreeze/stack.png and b/assets/images/oceanBreeze/stack.png differ
diff --git a/assets/images/oceanBreeze/stack.svg b/assets/images/oceanBreeze/stack.svg
new file mode 100644
index 000000000..43f29e515
--- /dev/null
+++ b/assets/images/oceanBreeze/stack.svg
@@ -0,0 +1,440 @@
+
diff --git a/assets/images/oceanBreeze/wownero.svg b/assets/images/oceanBreeze/wownero.svg
new file mode 100644
index 000000000..812123542
--- /dev/null
+++ b/assets/images/oceanBreeze/wownero.svg
@@ -0,0 +1,190 @@
+
diff --git a/assets/images/oledBlack/bitcoin.svg b/assets/images/oledBlack/bitcoin.svg
new file mode 100644
index 000000000..d3abd0954
--- /dev/null
+++ b/assets/images/oledBlack/bitcoin.svg
@@ -0,0 +1,84 @@
+
diff --git a/assets/images/oledBlack/bitcoincash.svg b/assets/images/oledBlack/bitcoincash.svg
new file mode 100644
index 000000000..6a10cce09
--- /dev/null
+++ b/assets/images/oledBlack/bitcoincash.svg
@@ -0,0 +1,118 @@
+
diff --git a/assets/images/oledBlack/doge.svg b/assets/images/oledBlack/doge.svg
new file mode 100644
index 000000000..2c1d693b4
--- /dev/null
+++ b/assets/images/oledBlack/doge.svg
@@ -0,0 +1,255 @@
+
diff --git a/assets/images/oledBlack/firo.svg b/assets/images/oledBlack/firo.svg
new file mode 100644
index 000000000..6f502205c
--- /dev/null
+++ b/assets/images/oledBlack/firo.svg
@@ -0,0 +1,198 @@
+
diff --git a/assets/images/oledBlack/litecoin.svg b/assets/images/oledBlack/litecoin.svg
new file mode 100644
index 000000000..f224c429f
--- /dev/null
+++ b/assets/images/oledBlack/litecoin.svg
@@ -0,0 +1,124 @@
+
diff --git a/assets/images/oledBlack/particl.svg b/assets/images/oledBlack/particl.svg
new file mode 100644
index 000000000..d15918985
--- /dev/null
+++ b/assets/images/oledBlack/particl.svg
@@ -0,0 +1,188 @@
+
diff --git a/assets/images/oledBlack/stack.svg b/assets/images/oledBlack/stack.svg
new file mode 100644
index 000000000..43f29e515
--- /dev/null
+++ b/assets/images/oledBlack/stack.svg
@@ -0,0 +1,440 @@
+
diff --git a/assets/images/oledBlack/wownero.svg b/assets/images/oledBlack/wownero.svg
new file mode 100644
index 000000000..812123542
--- /dev/null
+++ b/assets/images/oledBlack/wownero.svg
@@ -0,0 +1,190 @@
+
diff --git a/assets/svg/fruitSorbet/persona-easy-1.png b/assets/svg/fruitSorbet/persona-easy-1.png
new file mode 100644
index 000000000..f2dd39e2f
Binary files /dev/null and b/assets/svg/fruitSorbet/persona-easy-1.png differ
diff --git a/assets/svg/fruitSorbet/persona-incognito-1.png b/assets/svg/fruitSorbet/persona-incognito-1.png
new file mode 100644
index 000000000..16465fcff
Binary files /dev/null and b/assets/svg/fruitSorbet/persona-incognito-1.png differ
diff --git a/assets/svg/oceanBreeze/persona-easy-1.png b/assets/svg/oceanBreeze/persona-easy-1.png
new file mode 100644
index 000000000..20cafb519
Binary files /dev/null and b/assets/svg/oceanBreeze/persona-easy-1.png differ
diff --git a/assets/svg/oceanBreeze/persona-incognito-1.png b/assets/svg/oceanBreeze/persona-incognito-1.png
new file mode 100644
index 000000000..8453cfa76
Binary files /dev/null and b/assets/svg/oceanBreeze/persona-incognito-1.png differ
diff --git a/lib/exceptions/exchange/unsupported_currency_exception.dart b/lib/exceptions/exchange/unsupported_currency_exception.dart
new file mode 100644
index 000000000..9e4430de8
--- /dev/null
+++ b/lib/exceptions/exchange/unsupported_currency_exception.dart
@@ -0,0 +1,7 @@
+import 'package:stackwallet/exceptions/exchange/exchange_exception.dart';
+
+class UnsupportedCurrencyException extends ExchangeException {
+ UnsupportedCurrencyException(super.message, super.type, this.currency);
+
+ final String currency;
+}
diff --git a/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart b/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart
index 816a27cd2..bf479a08c 100644
--- a/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart
+++ b/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart
@@ -1,8 +1,12 @@
import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
-class CoinImage extends StatelessWidget {
+class CoinImage extends ConsumerWidget {
const CoinImage({
Key? key,
required this.coin,
@@ -13,12 +17,30 @@ class CoinImage extends StatelessWidget {
final bool isDesktop;
@override
- Widget build(BuildContext context) {
- return Image(
- image: AssetImage(
- Assets.png.imageFor(coin: coin, context: context),
- ),
- width: isDesktop ? 324 : MediaQuery.of(context).size.width / 3,
- );
+ Widget build(BuildContext context, WidgetRef ref) {
+ final bool isSorbet = ref.read(colorThemeProvider.state).state.themeType ==
+ ThemeType.fruitSorbet;
+ final bool isForest =
+ ref.read(colorThemeProvider.state).state.themeType == ThemeType.forest;
+
+ return ((isSorbet || isForest) &&
+ coin != Coin.epicCash &&
+ coin != Coin.monero &&
+ coin != Coin.namecoin)
+ ? ((isForest && coin != Coin.litecoin && coin != Coin.dogecoin)
+ ? SvgPicture.asset(
+ Assets.svg.imageFor(coin: coin, context: context),
+ width: isDesktop ? 324 : MediaQuery.of(context).size.width,
+ )
+ : Image(
+ image: AssetImage(
+ Assets.png.imageFor(coin: coin, context: context),
+ )))
+ : Image(
+ image: AssetImage(
+ Assets.png.imageFor(coin: coin, context: context),
+ ),
+ width: isDesktop ? 324 : MediaQuery.of(context).size.width / 3,
+ );
}
}
diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart
index bb17e91ee..aa1683c3f 100644
--- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart
+++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart
@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:isar/isar.dart';
+import 'package:stackwallet/exceptions/exchange/unsupported_currency_exception.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
@@ -106,6 +107,10 @@ class _ExchangeCurrencySelectionViewState
);
if (cn.value == null) {
+ if (cn.exception is UnsupportedCurrencyException) {
+ return currencies;
+ }
+
await showDialog(
context: context,
builder: (context) => StackDialog(
@@ -130,11 +135,11 @@ class _ExchangeCurrencySelectionViewState
currencies.addAll(cn.value!);
}
- return currencies;
+ return _getDistinctCurrenciesFrom(currencies);
}
Future> _getCurrencies() async {
- return ExchangeDataLoadingService.instance.isar.currencies
+ final currencies = await ExchangeDataLoadingService.instance.isar.currencies
.where()
.filter()
.isFiatEqualTo(false)
@@ -150,22 +155,40 @@ class _ExchangeCurrencySelectionViewState
.rateTypeEqualTo(SupportedRateType.estimated))
.sortByIsStackCoin()
.thenByName()
- .distinctByTicker(caseSensitive: false)
.findAll();
+
+ return _getDistinctCurrenciesFrom(currencies);
+ }
+
+ List _getDistinctCurrenciesFrom(List currencies) {
+ final List distinctCurrencies = [];
+ for (final currency in currencies) {
+ if (!distinctCurrencies.any((e) => e.ticker == currency.ticker)) {
+ distinctCurrencies.add(currency);
+ }
+ }
+ return distinctCurrencies;
}
List filter(String text) {
- if (text.isEmpty) {
- return _currencies;
- }
-
if (widget.pairedTicker == null) {
+ if (text.isEmpty) {
+ return _currencies;
+ }
+
return _currencies
.where((e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase()))
.toList(growable: false);
} else {
+ if (text.isEmpty) {
+ return _currencies
+ .where((e) =>
+ e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase())
+ .toList(growable: false);
+ }
+
return _currencies
.where((e) =>
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() &&
diff --git a/lib/pages/paynym/add_new_paynym_follow_view.dart b/lib/pages/paynym/add_new_paynym_follow_view.dart
index b5c1ba85e..68473fc7c 100644
--- a/lib/pages/paynym/add_new_paynym_follow_view.dart
+++ b/lib/pages/paynym/add_new_paynym_follow_view.dart
@@ -445,6 +445,7 @@ class _AddNewPaynymFollowViewState
.backgroundAppBar
: null,
child: PaynymCard(
+ key: UniqueKey(),
label: _searchResult!.nymName,
paymentCodeString: _searchResult!.codes.first.code,
walletId: widget.walletId,
diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart
index 729ed5941..c6dedeb39 100644
--- a/lib/pages/paynym/dialogs/paynym_details_popup.dart
+++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart
@@ -26,6 +26,7 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
+import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:tuple/tuple.dart';
class PaynymDetailsPopup extends ConsumerStatefulWidget {
@@ -102,6 +103,20 @@ class _PaynymDetailsPopupState extends ConsumerState {
_showInsufficientFundsInfo = true;
});
return;
+ } catch (e) {
+ if (mounted) {
+ canPop = true;
+ Navigator.of(context).pop();
+ }
+
+ await showDialog(
+ context: context,
+ builder: (context) => StackOkDialog(
+ title: "Error",
+ message: e.toString(),
+ ),
+ );
+ return;
}
if (mounted) {
diff --git a/lib/pages/stack_privacy_calls.dart b/lib/pages/stack_privacy_calls.dart
index 5ec5b881d..474b521d1 100644
--- a/lib/pages/stack_privacy_calls.dart
+++ b/lib/pages/stack_privacy_calls.dart
@@ -12,6 +12,7 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
@@ -299,12 +300,16 @@ class _PrivacyToggleState extends ConsumerState {
late bool externalCallsEnabled;
late final bool isDesktop;
- late final bool usePNG;
+ late final bool isSorbet;
+ late final bool isOcean;
@override
void initState() {
isDesktop = Util.isDesktop;
- usePNG = ref.read(colorThemeProvider.state).state == "fruitSorbet";
+ isSorbet = ref.read(colorThemeProvider.state).state.themeType ==
+ ThemeType.fruitSorbet;
+ isOcean = ref.read(colorThemeProvider.state).state.themeType ==
+ ThemeType.oceanBreeze;
// initial toggle state
externalCallsEnabled = widget.externalCallsEnabled;
super.initState();
@@ -348,22 +353,25 @@ class _PrivacyToggleState extends ConsumerState {
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- if (isDesktop)
- const SizedBox(
- height: 10,
- ),
- // Image.asset(
- // // Assets.png.personaEasy,
- // ),
- SvgPicture.asset(
- Assets.svg.personaEasy(context),
- width: isDesktop ? 120 : 140,
- height: isDesktop ? 120 : 140,
- ),
- if (isDesktop)
- const SizedBox(
- height: 12,
- ),
+ // if (isDesktop)
+ // const SizedBox(
+ // height: 10,
+ // ),
+ (isSorbet || isOcean)
+ ? Image.asset(
+ Assets.png.personaEasy(context),
+ width: 140,
+ height: 140,
+ )
+ : SvgPicture.asset(
+ Assets.svg.personaEasy(context),
+ width: 140,
+ height: 140,
+ ),
+ // if (isDesktop)
+ // const SizedBox(
+ // height: 12,
+ // ),
Center(
child: Text(
"Easy Crypto",
diff --git a/lib/pages/wallets_view/sub_widgets/empty_wallets.dart b/lib/pages/wallets_view/sub_widgets/empty_wallets.dart
index 7391eca9d..09c6a876f 100644
--- a/lib/pages/wallets_view/sub_widgets/empty_wallets.dart
+++ b/lib/pages/wallets_view/sub_widgets/empty_wallets.dart
@@ -1,19 +1,26 @@
import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart';
+import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
-class EmptyWallets extends StatelessWidget {
+class EmptyWallets extends ConsumerWidget {
const EmptyWallets({Key? key}) : super(key: key);
@override
- Widget build(BuildContext context) {
+ Widget build(BuildContext context, WidgetRef ref) {
debugPrint("BUILD: $runtimeType");
final isDesktop = Util.isDesktop;
+ final bool isSorbet = ref.read(colorThemeProvider.state).state.themeType ==
+ ThemeType.fruitSorbet;
+ final bool isForest =
+ ref.read(colorThemeProvider.state).state.themeType == ThemeType.forest;
return SafeArea(
child: Padding(
@@ -29,12 +36,21 @@ class EmptyWallets extends StatelessWidget {
const Spacer(
flex: 2,
),
- Image(
- image: AssetImage(
- Assets.png.stack(context),
- ),
- width: isDesktop ? 324 : MediaQuery.of(context).size.width / 3,
- ),
+ (isSorbet || isForest)
+ ? SvgPicture.asset(
+ Assets.svg.stack(context),
+ width: isDesktop
+ ? 324
+ : MediaQuery.of(context).size.width / 3,
+ )
+ : Image(
+ image: AssetImage(
+ Assets.png.stack(context),
+ ),
+ width: isDesktop
+ ? 324
+ : MediaQuery.of(context).size.width / 3,
+ ),
SizedBox(
height: isDesktop ? 30 : 16,
),
diff --git a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart
index a2591e57a..cb24fbd6f 100644
--- a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart
+++ b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart
@@ -10,6 +10,7 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
@@ -18,6 +19,8 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
+import '../../../../providers/ui/color_theme_provider.dart';
+
class StackPrivacyDialog extends ConsumerStatefulWidget {
const StackPrivacyDialog({Key? key}) : super(key: key);
@@ -149,7 +152,9 @@ class _StackPrivacyDialog extends ConsumerState {
Expanded(
child: SecondaryButton(
label: "Cancel",
- onPressed: () {},
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
),
),
const SizedBox(
@@ -192,7 +197,7 @@ class _StackPrivacyDialog extends ConsumerState {
}
}
-class PrivacyToggle extends StatefulWidget {
+class PrivacyToggle extends ConsumerStatefulWidget {
const PrivacyToggle({
Key? key,
required this.externalCallsEnabled,
@@ -203,17 +208,23 @@ class PrivacyToggle extends StatefulWidget {
final void Function(bool)? onChanged;
@override
- State createState() => _PrivacyToggleState();
+ ConsumerState createState() => _PrivacyToggleState();
}
-class _PrivacyToggleState extends State {
+class _PrivacyToggleState extends ConsumerState {
late bool externalCallsEnabled;
late final bool isDesktop;
+ late final bool isSorbet;
+ late final bool isOcean;
@override
void initState() {
isDesktop = Util.isDesktop;
+ isSorbet = ref.read(colorThemeProvider.state).state.themeType ==
+ ThemeType.fruitSorbet;
+ isOcean = ref.read(colorThemeProvider.state).state.themeType ==
+ ThemeType.oceanBreeze;
// initial toggle state
externalCallsEnabled = widget.externalCallsEnabled;
super.initState();
@@ -262,11 +273,17 @@ class _PrivacyToggleState extends State {
const SizedBox(
height: 10,
),
- SvgPicture.asset(
- Assets.svg.personaEasy(context),
- width: 120,
- height: 120,
- ),
+ (isSorbet || isOcean)
+ ? Image.asset(
+ Assets.png.personaEasy(context),
+ width: 120,
+ height: 120,
+ )
+ : SvgPicture.asset(
+ Assets.svg.personaEasy(context),
+ width: 120,
+ height: 120,
+ ),
if (isDesktop)
const SizedBox(
height: 12,
@@ -368,11 +385,17 @@ class _PrivacyToggleState extends State {
const SizedBox(
height: 10,
),
- SvgPicture.asset(
- Assets.svg.personaIncognito(context),
- width: 120,
- height: 120,
- ),
+ (isSorbet || isOcean)
+ ? Image.asset(
+ Assets.png.personaIncognito(context),
+ width: 120,
+ height: 120,
+ )
+ : SvgPicture.asset(
+ Assets.svg.personaIncognito(context),
+ width: 120,
+ height: 120,
+ ),
if (isDesktop)
const SizedBox(
height: 12,
diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart
index 35bfd2906..bdb6b7add 100644
--- a/lib/services/coins/epiccash/epiccash_wallet.dart
+++ b/lib/services/coins/epiccash/epiccash_wallet.dart
@@ -6,7 +6,6 @@ import 'dart:isolate';
import 'package:decimal/decimal.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_libepiccash/epic_cash.dart';
-import 'package:http/http.dart';
import 'package:isar/isar.dart';
import 'package:mutex/mutex.dart';
import 'package:stack_wallet_backup/generate_password.dart';
@@ -37,6 +36,7 @@ import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
import 'package:tuple/tuple.dart';
+import 'package:websocket_universal/websocket_universal.dart';
const int MINIMUM_CONFIRMATIONS = 10;
@@ -462,6 +462,18 @@ class EpicCashWallet extends CoinServiceAPI
dynamic message;
String receiverAddress = txData['addresss'] as String;
+
+ if (!receiverAddress.startsWith("http://") ||
+ !receiverAddress.startsWith("https://")) {
+ final decoded = json.decode(epicboxConfig);
+ bool isEpicboxConnected = await testEpicboxServer(
+ decoded["epicbox_domain"] as String,
+ decoded["epicbox_port"] as int);
+ if (!isEpicboxConnected) {
+ throw Exception("Failed to send TX : Unable to reach epicbox server");
+ }
+ }
+
await m.protect(() async {
if (receiverAddress.startsWith("http://") ||
receiverAddress.startsWith("https://")) {
@@ -980,22 +992,75 @@ class EpicCashWallet extends CoinServiceAPI
return stringConfig;
}
+ Future testEpicboxServer(String host, int port) async {
+ final websocketConnectionUri = 'wss://$host:$port';
+ const connectionOptions = SocketConnectionOptions(
+ pingIntervalMs: 3000,
+ timeoutConnectionMs: 4000,
+
+ /// see ping/pong messages in [logEventStream] stream
+ skipPingMessages: true,
+
+ /// Set this attribute to `true` if do not need any ping/pong
+ /// messages and ping measurement. Default is `false`
+ pingRestrictionForce: false,
+ );
+
+ final IMessageProcessor textSocketProcessor =
+ SocketSimpleTextProcessor();
+ final textSocketHandler = IWebSocketHandler.createClient(
+ websocketConnectionUri,
+ textSocketProcessor,
+ connectionOptions: connectionOptions,
+ );
+
+ // Listening to server responses:
+ bool isConnected = true;
+ textSocketHandler.incomingMessagesStream.listen((inMsg) {
+ Logging.instance.log(
+ '> webSocket got text message from server: "$inMsg" '
+ '[ping: ${textSocketHandler.pingDelayMs}]',
+ level: LogLevel.Info);
+ });
+
+ // Connecting to server:
+ final isTextSocketConnected = await textSocketHandler.connect();
+ if (!isTextSocketConnected) {
+ // ignore: avoid_print
+ Logging.instance.log(
+ 'Connection to [$websocketConnectionUri] failed for some reason!',
+ level: LogLevel.Error);
+ isConnected = false;
+ }
+ return isConnected;
+ }
+
Future getEpicBoxConfig() async {
- final storedConfig =
+ String? storedConfig =
await _secureStore.read(key: '${_walletId}_epicboxConfig');
- if (storedConfig != null) {
- final decoded = json.decode(storedConfig!);
+ if (storedConfig == null) {
+ return json.encode(DefaultNodes.defaultEpicBoxConfig);
+ } else {
+ dynamic decoded = json.decode(storedConfig!);
final domain = decoded["domain"] ?? "empty";
if (domain != "empty") {
- //If we have the old invalid config - update
- await _secureStore.write(
- key: '${_walletId}_epicboxConfig',
- value: DefaultNodes.defaultEpicBoxConfig);
+ //If we have the old invalid config, use the new default one
+ // new storage format stores domain under "epicbox_domain", old storage format used "domain"
+ storedConfig = DefaultNodes.defaultEpicBoxConfig;
+ decoded = json.decode(storedConfig);
}
- return await _secureStore.read(key: '${_walletId}_epicboxConfig') ??
- DefaultNodes.defaultEpicBoxConfig;
+ //Check Epicbox is up before returning it
+ bool isEpicboxConnected = await testEpicboxServer(
+ decoded["epicbox_domain"] as String, decoded["epicbox_port"] as int);
+
+ if (!isEpicboxConnected) {
+ //Default Epicbox is not connected, Defaulting to Europe
+ storedConfig = json.encode(DefaultNodes.epicBoxConfigEUR);
+ // TODO test this connection before returning it, iterating through the list of default Epic Box servers
+ }
+
+ return storedConfig;
}
- return DefaultNodes.defaultEpicBoxConfig;
}
Future getRealConfig() async {
diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart
index 99171a62f..cc9a14182 100644
--- a/lib/services/exchange/change_now/change_now_api.dart
+++ b/lib/services/exchange/change_now/change_now_api.dart
@@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:stackwallet/exceptions/exchange/exchange_exception.dart';
import 'package:stackwallet/exceptions/exchange/pair_unavailable_exception.dart';
+import 'package:stackwallet/exceptions/exchange/unsupported_currency_exception.dart';
import 'package:stackwallet/external_api_keys.dart';
import 'package:stackwallet/models/exchange/change_now/cn_exchange_estimate.dart';
import 'package:stackwallet/models/exchange/change_now/estimated_exchange_amount.dart';
@@ -49,9 +50,16 @@ class ChangeNowAPI {
headers: {'Content-Type': 'application/json'},
);
- final parsed = jsonDecode(response.body);
+ try {
+ final parsed = jsonDecode(response.body);
- return parsed;
+ return parsed;
+ } on FormatException catch (e) {
+ return {
+ "error": "Dart format exception",
+ "message": response.body,
+ };
+ }
} catch (e, s) {
Logging.instance
.log("_makeRequest($uri) threw: $e\n$s", level: LogLevel.Error);
@@ -207,7 +215,20 @@ class ChangeNowAPI {
try {
// json array is expected here
- final jsonArray = (await _makeGetRequest(uri)) as List;
+
+ final response = await _makeGetRequest(uri);
+
+ if (response is Map && response["error"] != null) {
+ return ExchangeResponse(
+ exception: UnsupportedCurrencyException(
+ response["message"] as String? ?? response["error"].toString(),
+ ExchangeExceptionType.generic,
+ ticker,
+ ),
+ );
+ }
+
+ final jsonArray = response as List;
List currencies = [];
try {
diff --git a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart
index fe6216e07..67012ad9b 100644
--- a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart
+++ b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart
@@ -21,6 +21,13 @@ class MajesticBankExchange extends Exchange {
static const exchangeName = "Majestic Bank";
+ static const kMajesticBankCurrencyNames = {
+ "BTC": "Bitcoin",
+ "LTC": "Litecoin",
+ "WOW": "Wownero",
+ "XMR": "Monero",
+ };
+
@override
Future> createTrade({
required String from,
@@ -110,7 +117,8 @@ class MajesticBankExchange extends Exchange {
final currency = Currency(
exchangeName: MajesticBankExchange.exchangeName,
ticker: limit.currency,
- name: limit.currency, // todo: get full coin name
+ name: kMajesticBankCurrencyNames[limit.currency] ??
+ limit.currency, // todo: add more names if MB adds more
network: "",
image: "",
isFiat: false,
diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart
index 876d863e3..774c7c609 100644
--- a/lib/services/mixins/paynym_wallet_interface.dart
+++ b/lib/services/mixins/paynym_wallet_interface.dart
@@ -27,6 +27,8 @@ import 'package:tuple/tuple.dart';
const kPaynymDerivePath = "m/47'/0'/0'";
mixin PaynymWalletInterface {
+ static const String _connectedKeyPrefix = "paynym_connected_";
+
// passed in wallet data
late final String _walletId;
late final String _walletName;
@@ -396,135 +398,162 @@ mixin PaynymWalletInterface {
int additionalOutputs = 0,
List? utxos,
}) async {
- final amountToSend = _dustLimitP2PKH;
- final List availableOutputs =
- utxos ?? await _db.getUTXOs(_walletId).findAll();
- final List spendableOutputs = [];
- int spendableSatoshiValue = 0;
+ try {
+ final amountToSend = _dustLimitP2PKH;
+ final List availableOutputs =
+ utxos ?? await _db.getUTXOs(_walletId).findAll();
+ final List spendableOutputs = [];
+ int spendableSatoshiValue = 0;
- // Build list of spendable outputs and totaling their satoshi amount
- for (var i = 0; i < availableOutputs.length; i++) {
- if (availableOutputs[i].isBlocked == false &&
- availableOutputs[i]
- .isConfirmed(await _getChainHeight(), _minConfirms) ==
- true) {
- spendableOutputs.add(availableOutputs[i]);
- spendableSatoshiValue += availableOutputs[i].value;
+ // Build list of spendable outputs and totaling their satoshi amount
+ for (var i = 0; i < availableOutputs.length; i++) {
+ if (availableOutputs[i].isBlocked == false &&
+ availableOutputs[i]
+ .isConfirmed(await _getChainHeight(), _minConfirms) ==
+ true) {
+ spendableOutputs.add(availableOutputs[i]);
+ spendableSatoshiValue += availableOutputs[i].value;
+ }
}
- }
- if (spendableSatoshiValue < amountToSend) {
- // insufficient balance
- throw InsufficientBalanceException(
- "Spendable balance is less than the minimum required for a notification transaction.");
- } else if (spendableSatoshiValue == amountToSend) {
- // insufficient balance due to missing amount to cover fee
- throw InsufficientBalanceException(
- "Remaining balance does not cover the network fee.");
- }
-
- // sort spendable by age (oldest first)
- spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!));
-
- int satoshisBeingUsed = 0;
- int outputsBeingUsed = 0;
- List utxoObjectsToUse = [];
-
- for (int i = 0;
- satoshisBeingUsed < amountToSend && i < spendableOutputs.length;
- i++) {
- utxoObjectsToUse.add(spendableOutputs[i]);
- satoshisBeingUsed += spendableOutputs[i].value;
- outputsBeingUsed += 1;
- }
-
- // add additional outputs if required
- for (int i = 0;
- i < additionalOutputs && outputsBeingUsed < spendableOutputs.length;
- i++) {
- utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]);
- satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value;
- outputsBeingUsed += 1;
- }
-
- // gather required signing data
- final utxoSigningData = await _fetchBuildTxData(utxoObjectsToUse);
-
- final int vSizeForNoChange = (await _createNotificationTx(
- targetPaymentCodeString: targetPaymentCodeString,
- utxosToUse: utxoObjectsToUse,
- utxoSigningData: utxoSigningData,
- change: 0))
- .item2;
-
- final int vSizeForWithChange = (await _createNotificationTx(
- targetPaymentCodeString: targetPaymentCodeString,
- utxosToUse: utxoObjectsToUse,
- utxoSigningData: utxoSigningData,
- change: satoshisBeingUsed - amountToSend))
- .item2;
-
- // Assume 2 outputs, for recipient and payment code script
- int feeForNoChange = _estimateTxFee(
- vSize: vSizeForNoChange,
- feeRatePerKB: selectedTxFeeRate,
- );
-
- // Assume 3 outputs, for recipient, payment code script, and change
- int feeForWithChange = _estimateTxFee(
- vSize: vSizeForWithChange,
- feeRatePerKB: selectedTxFeeRate,
- );
-
- if (_coin == Coin.dogecoin || _coin == Coin.dogecoinTestNet) {
- if (feeForNoChange < vSizeForNoChange * 1000) {
- feeForNoChange = vSizeForNoChange * 1000;
+ if (spendableSatoshiValue < amountToSend) {
+ // insufficient balance
+ throw InsufficientBalanceException(
+ "Spendable balance is less than the minimum required for a notification transaction.");
+ } else if (spendableSatoshiValue == amountToSend) {
+ // insufficient balance due to missing amount to cover fee
+ throw InsufficientBalanceException(
+ "Remaining balance does not cover the network fee.");
}
- if (feeForWithChange < vSizeForWithChange * 1000) {
- feeForWithChange = vSizeForWithChange * 1000;
+
+ // sort spendable by age (oldest first)
+ spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!));
+
+ int satoshisBeingUsed = 0;
+ int outputsBeingUsed = 0;
+ List utxoObjectsToUse = [];
+
+ for (int i = 0;
+ satoshisBeingUsed < amountToSend && i < spendableOutputs.length;
+ i++) {
+ utxoObjectsToUse.add(spendableOutputs[i]);
+ satoshisBeingUsed += spendableOutputs[i].value;
+ outputsBeingUsed += 1;
}
- }
- if (satoshisBeingUsed - amountToSend > feeForNoChange + _dustLimitP2PKH) {
- // try to add change output due to "left over" amount being greater than
- // the estimated fee + the dust limit
- int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange;
+ // add additional outputs if required
+ for (int i = 0;
+ i < additionalOutputs && outputsBeingUsed < spendableOutputs.length;
+ i++) {
+ utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]);
+ satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value;
+ outputsBeingUsed += 1;
+ }
- // check estimates are correct and build notification tx
- if (changeAmount >= _dustLimitP2PKH &&
- satoshisBeingUsed - amountToSend - changeAmount == feeForWithChange) {
- var txn = await _createNotificationTx(
- targetPaymentCodeString: targetPaymentCodeString,
- utxosToUse: utxoObjectsToUse,
- utxoSigningData: utxoSigningData,
- change: changeAmount,
- );
+ // gather required signing data
+ final utxoSigningData = await _fetchBuildTxData(utxoObjectsToUse);
- int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount;
+ final int vSizeForNoChange = (await _createNotificationTx(
+ targetPaymentCodeString: targetPaymentCodeString,
+ utxosToUse: utxoObjectsToUse,
+ utxoSigningData: utxoSigningData,
+ change: 0,
+ dustLimit:
+ satoshisBeingUsed, // override amount to get around absurd fees error
+ ))
+ .item2;
- // make sure minimum fee is accurate if that is being used
- if (txn.item2 - feeBeingPaid == 1) {
- changeAmount -= 1;
- feeBeingPaid += 1;
- txn = await _createNotificationTx(
+ final int vSizeForWithChange = (await _createNotificationTx(
+ targetPaymentCodeString: targetPaymentCodeString,
+ utxosToUse: utxoObjectsToUse,
+ utxoSigningData: utxoSigningData,
+ change: satoshisBeingUsed - amountToSend,
+ ))
+ .item2;
+
+ // Assume 2 outputs, for recipient and payment code script
+ int feeForNoChange = _estimateTxFee(
+ vSize: vSizeForNoChange,
+ feeRatePerKB: selectedTxFeeRate,
+ );
+
+ // Assume 3 outputs, for recipient, payment code script, and change
+ int feeForWithChange = _estimateTxFee(
+ vSize: vSizeForWithChange,
+ feeRatePerKB: selectedTxFeeRate,
+ );
+
+ if (_coin == Coin.dogecoin || _coin == Coin.dogecoinTestNet) {
+ if (feeForNoChange < vSizeForNoChange * 1000) {
+ feeForNoChange = vSizeForNoChange * 1000;
+ }
+ if (feeForWithChange < vSizeForWithChange * 1000) {
+ feeForWithChange = vSizeForWithChange * 1000;
+ }
+ }
+
+ if (satoshisBeingUsed - amountToSend > feeForNoChange + _dustLimitP2PKH) {
+ // try to add change output due to "left over" amount being greater than
+ // the estimated fee + the dust limit
+ int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange;
+
+ // check estimates are correct and build notification tx
+ if (changeAmount >= _dustLimitP2PKH &&
+ satoshisBeingUsed - amountToSend - changeAmount ==
+ feeForWithChange) {
+ var txn = await _createNotificationTx(
targetPaymentCodeString: targetPaymentCodeString,
utxosToUse: utxoObjectsToUse,
utxoSigningData: utxoSigningData,
change: changeAmount,
);
- }
- Map transactionObject = {
- "hex": txn.item1,
- "recipientPaynym": targetPaymentCodeString,
- "amount": amountToSend,
- "fee": feeBeingPaid,
- "vSize": txn.item2,
- };
- return transactionObject;
- } else {
- // something broke during fee estimation or the change amount is smaller
- // than the dust limit. Try without change
+ int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount;
+
+ // make sure minimum fee is accurate if that is being used
+ if (txn.item2 - feeBeingPaid == 1) {
+ changeAmount -= 1;
+ feeBeingPaid += 1;
+ txn = await _createNotificationTx(
+ targetPaymentCodeString: targetPaymentCodeString,
+ utxosToUse: utxoObjectsToUse,
+ utxoSigningData: utxoSigningData,
+ change: changeAmount,
+ );
+ }
+
+ Map transactionObject = {
+ "hex": txn.item1,
+ "recipientPaynym": targetPaymentCodeString,
+ "amount": amountToSend,
+ "fee": feeBeingPaid,
+ "vSize": txn.item2,
+ };
+ return transactionObject;
+ } else {
+ // something broke during fee estimation or the change amount is smaller
+ // than the dust limit. Try without change
+ final txn = await _createNotificationTx(
+ targetPaymentCodeString: targetPaymentCodeString,
+ utxosToUse: utxoObjectsToUse,
+ utxoSigningData: utxoSigningData,
+ change: 0,
+ );
+
+ int feeBeingPaid = satoshisBeingUsed - amountToSend;
+
+ Map transactionObject = {
+ "hex": txn.item1,
+ "recipientPaynym": targetPaymentCodeString,
+ "amount": amountToSend,
+ "fee": feeBeingPaid,
+ "vSize": txn.item2,
+ };
+ return transactionObject;
+ }
+ } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) {
+ // since we already checked if we need to add a change output we can just
+ // build without change here
final txn = await _createNotificationTx(
targetPaymentCodeString: targetPaymentCodeString,
utxosToUse: utxoObjectsToUse,
@@ -542,40 +571,22 @@ mixin PaynymWalletInterface {
"vSize": txn.item2,
};
return transactionObject;
- }
- } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) {
- // since we already checked if we need to add a change output we can just
- // build without change here
- final txn = await _createNotificationTx(
- targetPaymentCodeString: targetPaymentCodeString,
- utxosToUse: utxoObjectsToUse,
- utxoSigningData: utxoSigningData,
- change: 0,
- );
-
- int feeBeingPaid = satoshisBeingUsed - amountToSend;
-
- Map transactionObject = {
- "hex": txn.item1,
- "recipientPaynym": targetPaymentCodeString,
- "amount": amountToSend,
- "fee": feeBeingPaid,
- "vSize": txn.item2,
- };
- return transactionObject;
- } else {
- // if we get here we do not have enough funds to cover the tx total so we
- // check if we have any more available outputs and try again
- if (spendableOutputs.length > outputsBeingUsed) {
- return prepareNotificationTx(
- selectedTxFeeRate: selectedTxFeeRate,
- targetPaymentCodeString: targetPaymentCodeString,
- additionalOutputs: additionalOutputs + 1,
- );
} else {
- throw InsufficientBalanceException(
- "Remaining balance does not cover the network fee.");
+ // if we get here we do not have enough funds to cover the tx total so we
+ // check if we have any more available outputs and try again
+ if (spendableOutputs.length > outputsBeingUsed) {
+ return prepareNotificationTx(
+ selectedTxFeeRate: selectedTxFeeRate,
+ targetPaymentCodeString: targetPaymentCodeString,
+ additionalOutputs: additionalOutputs + 1,
+ );
+ } else {
+ throw InsufficientBalanceException(
+ "Remaining balance does not cover the network fee.");
+ }
}
+ } catch (e) {
+ rethrow;
}
}
@@ -586,85 +597,109 @@ mixin PaynymWalletInterface {
required List utxosToUse,
required Map utxoSigningData,
required int change,
+ int? dustLimit,
}) async {
- final targetPaymentCode =
- PaymentCode.fromPaymentCode(targetPaymentCodeString, _network);
- final myCode = await getPaymentCode(DerivePathType.bip44);
+ try {
+ final targetPaymentCode =
+ PaymentCode.fromPaymentCode(targetPaymentCodeString, _network);
+ final myCode = await getPaymentCode(DerivePathType.bip44);
- final utxo = utxosToUse.first;
- final txPoint = utxo.txid.fromHex.toList();
- final txPointIndex = utxo.vout;
+ final utxo = utxosToUse.first;
+ final txPoint = utxo.txid.fromHex.toList();
+ final txPointIndex = utxo.vout;
- final rev = Uint8List(txPoint.length + 4);
- Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length);
- final buffer = rev.buffer.asByteData();
- buffer.setUint32(txPoint.length, txPointIndex, Endian.little);
+ final rev = Uint8List(txPoint.length + 4);
+ Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length);
+ final buffer = rev.buffer.asByteData();
+ buffer.setUint32(txPoint.length, txPointIndex, Endian.little);
- final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair;
+ final myKeyPair =
+ utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair;
- final S = SecretPoint(
- myKeyPair.privateKey!,
- targetPaymentCode.notificationPublicKey(),
- );
+ final S = SecretPoint(
+ myKeyPair.privateKey!,
+ targetPaymentCode.notificationPublicKey(),
+ );
- final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev);
+ final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev);
- final blindedPaymentCode = PaymentCode.blind(
- payload: myCode.getPayload(),
- mask: blindingMask,
- unBlind: false,
- );
+ final blindedPaymentCode = PaymentCode.blind(
+ payload: myCode.getPayload(),
+ mask: blindingMask,
+ unBlind: false,
+ );
- final opReturnScript = bscript.compile([
- (op.OPS["OP_RETURN"] as int),
- blindedPaymentCode,
- ]);
+ final opReturnScript = bscript.compile([
+ (op.OPS["OP_RETURN"] as int),
+ blindedPaymentCode,
+ ]);
- // build a notification tx
- final txb = btc_dart.TransactionBuilder(network: _network);
- txb.setVersion(1);
+ // build a notification tx
+ final txb = btc_dart.TransactionBuilder(network: _network);
+ txb.setVersion(1);
- txb.addInput(
- utxo.txid,
- txPointIndex,
- null,
- utxoSigningData[utxo.txid]["output"] as Uint8List,
- );
+ txb.addInput(
+ utxo.txid,
+ txPointIndex,
+ null,
+ utxoSigningData[utxo.txid]["output"] as Uint8List,
+ );
- // todo: modify address once segwit support is in our bip47
- txb.addOutput(
- targetPaymentCode.notificationAddressP2PKH(), _dustLimitP2PKH);
- txb.addOutput(opReturnScript, 0);
+ // add rest of possible inputs
+ for (var i = 1; i < utxosToUse.length; i++) {
+ final utxo = utxosToUse[i];
+ txb.addInput(
+ utxo.txid,
+ utxo.vout,
+ null,
+ utxoSigningData[utxo.txid]["output"] as Uint8List,
+ );
+ }
- // TODO: add possible change output and mark output as dangerous
- if (change > 0) {
- // generate new change address if current change address has been used
- await _checkChangeAddressForTransactions();
- final String changeAddress = await _getCurrentChangeAddress();
- txb.addOutput(changeAddress, change);
- }
+ // todo: modify address once segwit support is in our bip47
+ txb.addOutput(
+ targetPaymentCode.notificationAddressP2PKH(),
+ dustLimit ?? _dustLimitP2PKH,
+ );
+ txb.addOutput(opReturnScript, 0);
- txb.sign(
- vin: 0,
- keyPair: myKeyPair,
- witnessValue: utxo.value,
- witnessScript: utxoSigningData[utxo.txid]["redeemScript"] as Uint8List?,
- );
+ // TODO: add possible change output and mark output as dangerous
+ if (change > 0) {
+ // generate new change address if current change address has been used
+ await _checkChangeAddressForTransactions();
+ final String changeAddress = await _getCurrentChangeAddress();
+ txb.addOutput(changeAddress, change);
+ }
- // sign rest of possible inputs
- for (var i = 1; i < utxosToUse.length; i++) {
- final txid = utxosToUse[i].txid;
txb.sign(
- vin: i,
- keyPair: utxoSigningData[txid]["keyPair"] as btc_dart.ECPair,
- witnessValue: utxosToUse[i].value,
+ vin: 0,
+ keyPair: myKeyPair,
+ witnessValue: utxo.value,
witnessScript: utxoSigningData[utxo.txid]["redeemScript"] as Uint8List?,
);
+
+ // sign rest of possible inputs
+ for (var i = 1; i < utxosToUse.length; i++) {
+ final txid = utxosToUse[i].txid;
+ txb.sign(
+ vin: i,
+ keyPair: utxoSigningData[txid]["keyPair"] as btc_dart.ECPair,
+ witnessValue: utxosToUse[i].value,
+ witnessScript:
+ utxoSigningData[utxo.txid]["redeemScript"] as Uint8List?,
+ );
+ }
+
+ final builtTx = txb.build();
+
+ return Tuple2(builtTx.toHex(), builtTx.virtualSize());
+ } catch (e, s) {
+ Logging.instance.log(
+ "_createNotificationTx(): $e\n$s",
+ level: LogLevel.Error,
+ );
+ rethrow;
}
-
- final builtTx = txb.build();
-
- return Tuple2(builtTx.toHex(), builtTx.virtualSize());
}
Future broadcastNotificationTx(
@@ -694,8 +729,41 @@ mixin PaynymWalletInterface {
}
}
+ // Future _checkHasConnectedCache(String paymentCodeString) async {
+ // final value = await _secureStorage.read(
+ // key: "$_connectedKeyPrefix$paymentCodeString");
+ // if (value == null) {
+ // return null;
+ // } else {
+ // final int rawBool = int.parse(value);
+ // return rawBool > 0;
+ // }
+ // }
+ //
+ // Future _setConnectedCache(
+ // String paymentCodeString, bool hasConnected) async {
+ // await _secureStorage.write(
+ // key: "$_connectedKeyPrefix$paymentCodeString",
+ // value: hasConnected ? "1" : "0");
+ // }
+
// TODO optimize
Future hasConnected(String paymentCodeString) async {
+ // final didConnect = await _checkHasConnectedCache(paymentCodeString);
+ // if (didConnect == true) {
+ // return true;
+ // }
+ //
+ // final keys = await lookupKey(paymentCodeString);
+ //
+ // final tx = await _db
+ // .getTransactions(_walletId)
+ // .filter()
+ // .subTypeEqualTo(TransactionSubType.bip47Notification).and()
+ // .address((q) =>
+ // q.anyOf(keys, (q, e) => q.otherDataEqualTo(e)))
+ // .findAll();
+
final myNotificationAddress =
await getMyNotificationAddress(DerivePathTypeExt.primaryFor(_coin));
@@ -706,29 +774,32 @@ mixin PaynymWalletInterface {
.findAll();
for (final tx in txns) {
- // quick check that may cause problems?
- if (tx.address.value?.value == myNotificationAddress.value) {
- return true;
- }
+ if (tx.type == TransactionType.incoming &&
+ tx.address.value?.value == myNotificationAddress.value) {
+ final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction(
+ transaction: tx,
+ myNotificationAddress: myNotificationAddress,
+ );
- final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction(
- transaction: tx,
- myNotificationAddress: myNotificationAddress,
- );
-
- if (paymentCodeString == unBlindedPaymentCode.toString()) {
- return true;
- }
-
- if (tx.address.value?.otherData != null) {
- final code = await paymentCodeStringByKey(tx.address.value!.otherData!);
- if (code == paymentCodeString) {
+ if (unBlindedPaymentCode != null &&
+ paymentCodeString == unBlindedPaymentCode.toString()) {
+ // await _setConnectedCache(paymentCodeString, true);
return true;
}
+ } else if (tx.type == TransactionType.outgoing) {
+ if (tx.address.value?.otherData != null) {
+ final code =
+ await paymentCodeStringByKey(tx.address.value!.otherData!);
+ if (code == paymentCodeString) {
+ // await _setConnectedCache(paymentCodeString, true);
+ return true;
+ }
+ }
}
}
// otherwise return no
+ // await _setConnectedCache(paymentCodeString, false);
return false;
}
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index d746984cf..5dee99bf1 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -99,6 +99,9 @@ class _SVG {
String personaEasy(BuildContext context) =>
"assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-easy-1.svg";
+ String stack(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/stack.svg";
+
String get themeFruit => "assets/svg/fruit-sorbet-theme.svg";
String get themeForest => "assets/svg/forest-theme.svg";
String get themeOledBlack => "assets/svg/oled-black-theme.svg";
@@ -209,6 +212,7 @@ class _SVG {
String get ellipse1 => "assets/svg/Ellipse-43.svg";
String get ellipse2 => "assets/svg/Ellipse-42.svg";
+ // small icons
String get bitcoin => "assets/svg/coin_icons/Bitcoin.svg";
String get litecoin => "assets/svg/coin_icons/Litecoin.svg";
String get bitcoincash => "assets/svg/coin_icons/Bitcoincash.svg";
@@ -267,6 +271,59 @@ class _SVG {
return dogecoinTestnet;
}
}
+
+ // big icons
+ String bitcoinImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/bitcoin.svg";
+ String bitcoincashImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/bitcoincash.svg";
+ String dogecoinImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/doge.svg";
+ // String get epicCashImage => "assets/images/fruitSorbet/epic-cash.svg";
+ String firoImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/firo.svg";
+ String litecoinImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/litecoin.svg";
+ // String get moneroImage => "assets/images/fruitSorbet/monero.svg";
+ String wowneroImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/wownero.svg";
+ // String get namecoinImage => "assets/images/fruitSorbet/Namecoin.svg";
+ String particlImage(BuildContext context) =>
+ "assets/images/${Theme.of(context).extension()!.themeType.name}/particl.svg";
+
+ String imageFor({required BuildContext context, required Coin coin}) {
+ switch (coin) {
+ case Coin.bitcoin:
+ return bitcoinImage(context);
+ case Coin.litecoin:
+ case Coin.litecoinTestNet:
+ return litecoinImage(context);
+ case Coin.bitcoincash:
+ return bitcoincashImage(context);
+ case Coin.dogecoin:
+ return dogecoinImage(context);
+ case Coin.epicCash:
+ return epicCash;
+ case Coin.firo:
+ return firoImage(context);
+ case Coin.monero:
+ return monero;
+ case Coin.wownero:
+ return wowneroImage(context);
+ case Coin.namecoin:
+ return namecoin;
+ case Coin.particl:
+ return particlImage(context);
+ case Coin.bitcoinTestNet:
+ return bitcoinImage(context);
+ case Coin.bitcoincashTestnet:
+ return bitcoincashImage(context);
+ case Coin.firoTestNet:
+ return firoImage(context);
+ case Coin.dogecoinTestNet:
+ return dogecoinImage(context);
+ }
+ }
}
class _PNG {
@@ -298,6 +355,11 @@ class _PNG {
String particl(BuildContext context) =>
"assets/images/${Theme.of(context).extension()!.themeType.name}/particl.png";
+ String personaIncognito(BuildContext context) =>
+ "assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-incognito-1.png";
+ String personaEasy(BuildContext context) =>
+ "assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-easy-1.png";
+
String get glasses => "assets/images/glasses.png";
String get glassesHidden => "assets/images/glasses-hidden.png";
diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart
index 6e8cc53cb..3348089a3 100644
--- a/lib/utilities/default_nodes.dart
+++ b/lib/utilities/default_nodes.dart
@@ -262,4 +262,11 @@ abstract class DefaultNodes {
"epicbox_protocol_unsecure": false,
"epicbox_address_index": 0,
});
+
+ static final String epicBoxConfigEUR = jsonEncode({
+ "epicbox_domain": "epicbox.fastepic.eu",
+ "epicbox_port": 443,
+ "epicbox_protocol_unsecure": false,
+ "epicbox_address_index": 0,
+ });
}
diff --git a/lib/utilities/text_styles.dart b/lib/utilities/text_styles.dart
index 11a1c3a97..6ff8cdaf1 100644
--- a/lib/utilities/text_styles.dart
+++ b/lib/utilities/text_styles.dart
@@ -990,7 +990,7 @@ class STextStyles {
);
case ThemeType.oledBlack:
return GoogleFonts.inter(
- color: _theme(context).infoItemIcons,
+ color: _theme(context).checkboxBGChecked,
fontWeight: FontWeight.w500,
fontSize: 14,
);
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 7c5023a1c..4f69a784b 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -13,9 +13,9 @@ import flutter_local_notifications
import flutter_secure_storage_macos
import isar_flutter_libs
import package_info_plus_macos
-import path_provider_macos
+import path_provider_foundation
import share_plus
-import shared_preferences_macos
+import shared_preferences_foundation
import stack_wallet_backup
import url_launcher_macos
import wakelock_macos
diff --git a/pubspec.lock b/pubspec.lock
index 12902104f..349ab50df 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -35,7 +35,7 @@ packages:
name: app_settings
url: "https://pub.dartlang.org"
source: hosted
- version: "4.1.8"
+ version: "4.2.0"
archive:
dependency: transitive
description:
@@ -49,7 +49,7 @@ packages:
name: args
url: "https://pub.dartlang.org"
source: hosted
- version: "2.3.1"
+ version: "2.4.0"
asn1lib:
dependency: transitive
description:
@@ -70,7 +70,7 @@ packages:
name: barcode_scan2
url: "https://pub.dartlang.org"
source: hosted
- version: "4.2.1"
+ version: "4.2.3"
bech32:
dependency: "direct main"
description:
@@ -100,8 +100,8 @@ packages:
dependency: "direct main"
description:
path: "."
- ref: "7b7c0b9284e7457f40dc60ea4420d8badf1aed39"
- resolved-ref: "7b7c0b9284e7457f40dc60ea4420d8badf1aed39"
+ ref: "48dd65f88822fba8543826274f6d51c17f735f93"
+ resolved-ref: "48dd65f88822fba8543826274f6d51c17f735f93"
url: "https://github.com/cypherstack/bip47.git"
source: git
version: "1.0.0"
@@ -192,7 +192,7 @@ packages:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
- version: "8.4.2"
+ version: "8.4.3"
characters:
dependency: transitive
description:
@@ -206,7 +206,7 @@ packages:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.1"
+ version: "2.0.2"
cli_util:
dependency: transitive
description:
@@ -227,7 +227,7 @@ packages:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
- version: "4.3.0"
+ version: "4.4.0"
collection:
dependency: transitive
description:
@@ -262,7 +262,7 @@ packages:
name: connectivity_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.3"
+ version: "1.2.4"
connectivity_plus_web:
dependency: transitive
description:
@@ -297,7 +297,7 @@ packages:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
- version: "0.3.3+2"
+ version: "0.3.3+4"
crypto:
dependency: "direct main"
description:
@@ -311,7 +311,7 @@ packages:
name: cryptography
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.5"
+ version: "2.1.1"
csslib:
dependency: transitive
description:
@@ -493,7 +493,7 @@ packages:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
- version: "5.2.3"
+ version: "5.2.5"
fixnum:
dependency: transitive
description:
@@ -587,7 +587,7 @@ packages:
name: flutter_native_splash
url: "https://pub.dartlang.org"
source: hosted
- version: "2.2.9"
+ version: "2.2.16"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@@ -622,7 +622,7 @@ packages:
name: flutter_secure_storage_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.2"
+ version: "1.1.3"
flutter_secure_storage_macos:
dependency: transitive
description:
@@ -777,7 +777,7 @@ packages:
name: image
url: "https://pub.dartlang.org"
source: hosted
- version: "3.2.2"
+ version: "3.3.0"
import_sorter:
dependency: "direct dev"
description:
@@ -803,7 +803,7 @@ packages:
name: io
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.3"
+ version: "1.0.4"
isar:
dependency: "direct main"
description:
@@ -838,7 +838,7 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
- version: "4.7.0"
+ version: "4.8.0"
jsonrpc2:
dependency: "direct main"
description:
@@ -860,13 +860,6 @@ packages:
relative: true
source: path
version: "0.0.1"
- lint:
- dependency: transitive
- description:
- name: lint
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.10.0"
lints:
dependency: transitive
description:
@@ -887,14 +880,14 @@ packages:
name: logging
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
lottie:
dependency: "direct main"
description:
name: lottie
url: "https://pub.dartlang.org"
source: hosted
- version: "1.4.2"
+ version: "1.4.3"
matcher:
dependency: transitive
description:
@@ -922,14 +915,14 @@ packages:
name: mime
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.3"
+ version: "1.0.4"
mobx:
dependency: transitive
description:
name: mobx
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.3"
+ version: "2.1.4"
mockingjay:
dependency: "direct dev"
description:
@@ -1048,7 +1041,7 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.11"
+ version: "2.0.12"
path_provider_android:
dependency: transitive
description:
@@ -1056,27 +1049,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.22"
- path_provider_ios:
+ path_provider_foundation:
dependency: transitive
description:
- name: path_provider_ios
+ name: path_provider_foundation
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.11"
+ version: "2.1.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.7"
- path_provider_macos:
- dependency: transitive
- description:
- name: path_provider_macos
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.6"
+ version: "2.1.8"
path_provider_platform_interface:
dependency: transitive
description:
@@ -1132,7 +1118,7 @@ packages:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
- version: "5.0.0"
+ version: "5.1.0"
platform:
dependency: transitive
description:
@@ -1244,7 +1230,7 @@ packages:
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
- version: "6.3.0"
+ version: "6.3.1"
share_plus_platform_interface:
dependency: transitive
description:
@@ -1258,35 +1244,28 @@ packages:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.15"
+ version: "2.0.17"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.14"
- shared_preferences_ios:
+ version: "2.0.15"
+ shared_preferences_foundation:
dependency: transitive
description:
- name: shared_preferences_ios
+ name: shared_preferences_foundation
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
+ version: "2.1.3"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
- shared_preferences_macos:
- dependency: transitive
- description:
- name: shared_preferences_macos
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.4"
+ version: "2.1.3"
shared_preferences_platform_interface:
dependency: transitive
description:
@@ -1307,7 +1286,7 @@ packages:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
+ version: "2.1.3"
shelf:
dependency: transitive
description:
@@ -1368,7 +1347,7 @@ packages:
name: source_maps
url: "https://pub.dartlang.org"
source: hosted
- version: "0.10.10"
+ version: "0.10.12"
source_span:
dependency: transitive
description:
@@ -1468,7 +1447,7 @@ packages:
name: time
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.2"
+ version: "2.1.3"
timezone:
dependency: transitive
description:
@@ -1482,14 +1461,14 @@ packages:
name: timing
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.0"
+ version: "1.0.1"
tint:
dependency: transitive
description:
name: tint
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.0.1"
toast:
dependency: "direct main"
description:
@@ -1517,42 +1496,42 @@ packages:
name: universal_io
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.4"
+ version: "2.2.0"
url_launcher:
dependency: "direct main"
description:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
- version: "6.1.7"
+ version: "6.1.9"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
url: "https://pub.dartlang.org"
source: hosted
- version: "6.0.22"
+ version: "6.0.23"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
url: "https://pub.dartlang.org"
source: hosted
- version: "6.0.17"
+ version: "6.1.0"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
url_launcher_platform_interface:
dependency: transitive
description:
@@ -1566,14 +1545,14 @@ packages:
name: url_launcher_web
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.13"
+ version: "2.0.14"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.1"
+ version: "3.0.3"
uuid:
dependency: "direct main"
description:
@@ -1643,7 +1622,7 @@ packages:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.2.0"
+ version: "2.3.0"
webdriver:
dependency: transitive
description:
@@ -1658,13 +1637,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
+ websocket_universal:
+ dependency: "direct main"
+ description:
+ name: websocket_universal
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.5.1"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
- version: "3.1.2"
+ version: "3.1.3"
window_size:
dependency: "direct main"
description:
@@ -1680,7 +1666,7 @@ packages:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.0+2"
+ version: "0.2.0+3"
xml:
dependency: transitive
description:
@@ -1711,4 +1697,4 @@ packages:
version: "1.0.0"
sdks:
dart: ">=2.18.5 <3.0.0"
- flutter: ">=3.0.1"
+ flutter: ">=3.3.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 46f6364a4..9332db35d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
-version: 1.5.40+127
+version: 1.5.43+130
environment:
sdk: ">=2.17.0 <3.0.0"
@@ -21,6 +21,7 @@ dependencies:
sdk: flutter
ffi: ^2.0.1
mutex: ^3.0.0
+ websocket_universal: ^0.5.1
lelantus:
path: ./crypto_plugins/flutter_liblelantus
diff --git a/test/services/change_now/change_now_test.dart b/test/services/change_now/change_now_test.dart
index 9fb27e0f1..f79cbcd4d 100644
--- a/test/services/change_now/change_now_test.dart
+++ b/test/services/change_now/change_now_test.dart
@@ -121,7 +121,8 @@ void main() {
final result = await ChangeNowAPI.instance.getAvailableCurrencies();
- expect(result.exception!.type, ExchangeExceptionType.generic);
+ expect(
+ result.exception!.type, ExchangeExceptionType.serializeResponseError);
expect(result.value == null, true);
});
});
@@ -263,7 +264,8 @@ void main() {
apiKey: "testAPIKEY",
);
- expect(result.exception!.type, ExchangeExceptionType.generic);
+ expect(
+ result.exception!.type, ExchangeExceptionType.serializeResponseError);
expect(result.value == null, true);
});
});
@@ -470,7 +472,8 @@ void main() {
apiKey: "testAPIKEY",
);
- expect(result.exception!.type, ExchangeExceptionType.generic);
+ expect(
+ result.exception!.type, ExchangeExceptionType.serializeResponseError);
expect(result.value == null, true);
});
});
@@ -721,7 +724,8 @@ void main() {
apiKey: "testAPIKEY",
);
- expect(result.exception!.type, ExchangeExceptionType.generic);
+ expect(
+ result.exception!.type, ExchangeExceptionType.serializeResponseError);
expect(result.value == null, true);
});
});
@@ -779,7 +783,8 @@ void main() {
final result =
await ChangeNowAPI.instance.getAvailableFloatingRatePairs();
- expect(result.exception!.type, ExchangeExceptionType.generic);
+ expect(
+ result.exception!.type, ExchangeExceptionType.serializeResponseError);
expect(result.value == null, true);
});
});