mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 03:49:22 +00:00
Merge branch 'staging' into docs
This commit is contained in:
commit
05df748b11
14 changed files with 285 additions and 185 deletions
|
@ -9,9 +9,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/models/buy/response_objects/order.dart';
|
import 'package:stackwallet/models/buy/response_objects/order.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/themes/theme_providers.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
@ -21,7 +23,7 @@ import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class BuyOrderDetailsView extends StatefulWidget {
|
class BuyOrderDetailsView extends ConsumerStatefulWidget {
|
||||||
const BuyOrderDetailsView({
|
const BuyOrderDetailsView({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.order,
|
required this.order,
|
||||||
|
@ -32,10 +34,11 @@ class BuyOrderDetailsView extends StatefulWidget {
|
||||||
static const String routeName = "/buyOrderDetails";
|
static const String routeName = "/buyOrderDetails";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<BuyOrderDetailsView> createState() => _BuyOrderDetailsViewState();
|
ConsumerState<BuyOrderDetailsView> createState() =>
|
||||||
|
_BuyOrderDetailsViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BuyOrderDetailsViewState extends State<BuyOrderDetailsView> {
|
class _BuyOrderDetailsViewState extends ConsumerState<BuyOrderDetailsView> {
|
||||||
final isDesktop = Util.isDesktop;
|
final isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -245,7 +248,9 @@ class _BuyOrderDetailsViewState extends State<BuyOrderDetailsView> {
|
||||||
width: 64,
|
width: 64,
|
||||||
height: 32,
|
height: 32,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.buy.simplexLogo(context),
|
Assets.buy.simplexLogo(
|
||||||
|
ref.watch(themeProvider).brightness,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -11,11 +11,13 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/sub_widgets/buy_warning_popup.dart';
|
import 'package:stackwallet/pages/buy_view/sub_widgets/buy_warning_popup.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/themes/theme_providers.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
@ -25,7 +27,7 @@ import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class BuyQuotePreviewView extends StatefulWidget {
|
class BuyQuotePreviewView extends ConsumerStatefulWidget {
|
||||||
const BuyQuotePreviewView({
|
const BuyQuotePreviewView({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.quote,
|
required this.quote,
|
||||||
|
@ -36,10 +38,11 @@ class BuyQuotePreviewView extends StatefulWidget {
|
||||||
static const String routeName = "/buyQuotePreview";
|
static const String routeName = "/buyQuotePreview";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<BuyQuotePreviewView> createState() => _BuyQuotePreviewViewState();
|
ConsumerState<BuyQuotePreviewView> createState() =>
|
||||||
|
_BuyQuotePreviewViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BuyQuotePreviewViewState extends State<BuyQuotePreviewView> {
|
class _BuyQuotePreviewViewState extends ConsumerState<BuyQuotePreviewView> {
|
||||||
final isDesktop = Util.isDesktop;
|
final isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
Future<void> _buyWarning() async {
|
Future<void> _buyWarning() async {
|
||||||
|
@ -222,7 +225,9 @@ class _BuyQuotePreviewViewState extends State<BuyQuotePreviewView> {
|
||||||
width: 64,
|
width: 64,
|
||||||
height: 32,
|
height: 32,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.buy.simplexLogo(context),
|
Assets.buy.simplexLogo(
|
||||||
|
ref.watch(themeProvider).brightness,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/models/buy/response_objects/order.dart';
|
import 'package:stackwallet/models/buy/response_objects/order.dart';
|
||||||
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||||
|
@ -18,6 +19,7 @@ import 'package:stackwallet/pages/buy_view/buy_order_details.dart';
|
||||||
import 'package:stackwallet/services/buy/buy_response.dart';
|
import 'package:stackwallet/services/buy/buy_response.dart';
|
||||||
import 'package:stackwallet/services/buy/simplex/simplex_api.dart';
|
import 'package:stackwallet/services/buy/simplex/simplex_api.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/themes/theme_providers.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
@ -28,7 +30,7 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||||
|
|
||||||
class BuyWarningPopup extends StatefulWidget {
|
class BuyWarningPopup extends ConsumerStatefulWidget {
|
||||||
const BuyWarningPopup({
|
const BuyWarningPopup({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.quote,
|
required this.quote,
|
||||||
|
@ -37,10 +39,10 @@ class BuyWarningPopup extends StatefulWidget {
|
||||||
final SimplexQuote quote;
|
final SimplexQuote quote;
|
||||||
final SimplexOrder? order;
|
final SimplexOrder? order;
|
||||||
@override
|
@override
|
||||||
State<BuyWarningPopup> createState() => _BuyWarningPopupState();
|
ConsumerState<BuyWarningPopup> createState() => _BuyWarningPopupState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BuyWarningPopupState extends State<BuyWarningPopup> {
|
class _BuyWarningPopupState extends ConsumerState<BuyWarningPopup> {
|
||||||
late final bool isDesktop;
|
late final bool isDesktop;
|
||||||
SimplexOrder? order;
|
SimplexOrder? order;
|
||||||
|
|
||||||
|
@ -236,7 +238,9 @@ class _BuyWarningPopupState extends State<BuyWarningPopup> {
|
||||||
width: 64,
|
width: 64,
|
||||||
height: 32,
|
height: 32,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.buy.simplexLogo(context),
|
Assets.buy.simplexLogo(
|
||||||
|
ref.watch(themeProvider).brightness,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -291,7 +295,9 @@ class _BuyWarningPopupState extends State<BuyWarningPopup> {
|
||||||
width: 64,
|
width: 64,
|
||||||
height: 32,
|
height: 32,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.buy.simplexLogo(context),
|
Assets.buy.simplexLogo(
|
||||||
|
ref.watch(themeProvider).brightness,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,6 +22,7 @@ import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_vi
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:stackwallet/route_generator.dart';
|
import 'package:stackwallet/route_generator.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
@ -337,7 +338,11 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
QrImageView(
|
QrImageView(
|
||||||
data: "${coin.uriScheme}:$receivingAddress",
|
data: AddressUtils.buildUriString(
|
||||||
|
coin,
|
||||||
|
receivingAddress,
|
||||||
|
{},
|
||||||
|
),
|
||||||
size: MediaQuery.of(context).size.width / 2,
|
size: MediaQuery.of(context).size.width / 2,
|
||||||
foregroundColor: Theme.of(context)
|
foregroundColor: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
|
|
|
@ -21,6 +21,7 @@ import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:stackwallet/route_generator.dart';
|
import 'package:stackwallet/route_generator.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
@ -236,7 +237,11 @@ class _DesktopReceiveState extends ConsumerState<DesktopReceive> {
|
||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: QrImageView(
|
child: QrImageView(
|
||||||
data: "${coin.uriScheme}:$receivingAddress",
|
data: AddressUtils.buildUriString(
|
||||||
|
coin,
|
||||||
|
receivingAddress,
|
||||||
|
{},
|
||||||
|
),
|
||||||
size: 200,
|
size: 200,
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
Theme.of(context).extension<StackColors>()!.accentColorDark,
|
Theme.of(context).extension<StackColors>()!.accentColorDark,
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:bip47/bip47.dart';
|
import 'package:bip47/bip47.dart';
|
||||||
import 'package:cw_core/monero_transaction_priority.dart';
|
import 'package:cw_core/monero_transaction_priority.dart';
|
||||||
|
@ -462,27 +461,11 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
|
|
||||||
void _cryptoAmountChanged() async {
|
void _cryptoAmountChanged() async {
|
||||||
if (!_cryptoAmountChangeLock) {
|
if (!_cryptoAmountChangeLock) {
|
||||||
String cryptoAmount = cryptoAmountController.text;
|
final cryptoAmount = ref.read(pAmountFormatter(coin)).tryParse(
|
||||||
if (cryptoAmount.isNotEmpty &&
|
cryptoAmountController.text,
|
||||||
cryptoAmount != "." &&
|
);
|
||||||
cryptoAmount != ",") {
|
if (cryptoAmount != null) {
|
||||||
if (cryptoAmount.startsWith("~")) {
|
_amountToSend = cryptoAmount;
|
||||||
cryptoAmount = cryptoAmount.substring(1);
|
|
||||||
}
|
|
||||||
if (cryptoAmount.contains(" ")) {
|
|
||||||
cryptoAmount = cryptoAmount.split(" ").first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure we don't shift past minimum atomic value
|
|
||||||
final shift = min(ref.read(pAmountUnit(coin)).shift, coin.decimals);
|
|
||||||
|
|
||||||
_amountToSend = cryptoAmount.contains(",")
|
|
||||||
? Decimal.parse(cryptoAmount.replaceFirst(",", "."))
|
|
||||||
.shift(0 - shift)
|
|
||||||
.toAmount(fractionDigits: coin.decimals)
|
|
||||||
: Decimal.parse(cryptoAmount)
|
|
||||||
.shift(0 - shift)
|
|
||||||
.toAmount(fractionDigits: coin.decimals);
|
|
||||||
if (_cachedAmountToSend != null &&
|
if (_cachedAmountToSend != null &&
|
||||||
_cachedAmountToSend == _amountToSend) {
|
_cachedAmountToSend == _amountToSend) {
|
||||||
return;
|
return;
|
||||||
|
@ -677,15 +660,12 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fiatTextFieldOnChanged(String baseAmountString) {
|
void fiatTextFieldOnChanged(String baseAmountString) {
|
||||||
if (baseAmountString.isNotEmpty &&
|
final baseAmount = Amount.tryParseFiatString(
|
||||||
baseAmountString != "." &&
|
baseAmountString,
|
||||||
baseAmountString != ",") {
|
locale: ref.read(localeServiceChangeNotifierProvider).locale,
|
||||||
final baseAmount = baseAmountString.contains(",")
|
);
|
||||||
? Decimal.parse(baseAmountString.replaceFirst(",", "."))
|
if (baseAmount != null) {
|
||||||
.toAmount(fractionDigits: 2)
|
final _price =
|
||||||
: Decimal.parse(baseAmountString).toAmount(fractionDigits: 2);
|
|
||||||
|
|
||||||
var _price =
|
|
||||||
ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1;
|
ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1;
|
||||||
|
|
||||||
if (_price == Decimal.zero) {
|
if (_price == Decimal.zero) {
|
||||||
|
@ -1389,7 +1369,10 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
),
|
),
|
||||||
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
||||||
ConditionalParent(
|
ConditionalParent(
|
||||||
condition: coin.isElectrumXCoin,
|
condition: coin.isElectrumXCoin &&
|
||||||
|
!(((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
|
ref.read(publicPrivateBalanceStateProvider.state).state ==
|
||||||
|
"Private")),
|
||||||
builder: (child) => Row(
|
builder: (child) => Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
@ -1441,72 +1424,117 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
),
|
),
|
||||||
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
if (!([Coin.nano, Coin.banano, Coin.epicCash].contains(coin)))
|
||||||
if (!isCustomFee)
|
if (!isCustomFee)
|
||||||
(feeSelectionResult?.$2 == null)
|
Padding(
|
||||||
? FutureBuilder(
|
padding: const EdgeInsets.all(10),
|
||||||
future: ref.watch(
|
child: (feeSelectionResult?.$2 == null)
|
||||||
walletsChangeNotifierProvider.select(
|
? FutureBuilder(
|
||||||
(value) => value.getManager(walletId).fees,
|
future: ref.watch(
|
||||||
|
walletsChangeNotifierProvider.select(
|
||||||
|
(value) => value.getManager(walletId).fees,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
builder: (context, snapshot) {
|
||||||
builder: (context, snapshot) {
|
if (snapshot.connectionState == ConnectionState.done &&
|
||||||
if (snapshot.connectionState == ConnectionState.done &&
|
snapshot.hasData) {
|
||||||
snapshot.hasData) {
|
return DesktopFeeItem(
|
||||||
return DesktopFeeItem(
|
feeObject: snapshot.data,
|
||||||
feeObject: snapshot.data,
|
feeRateType: FeeRateType.average,
|
||||||
feeRateType: FeeRateType.average,
|
walletId: walletId,
|
||||||
walletId: walletId,
|
isButton: false,
|
||||||
feeFor: ({
|
feeFor: ({
|
||||||
required Amount amount,
|
required Amount amount,
|
||||||
required FeeRateType feeRateType,
|
required FeeRateType feeRateType,
|
||||||
required int feeRate,
|
required int feeRate,
|
||||||
required Coin coin,
|
required Coin coin,
|
||||||
}) async {
|
}) async {
|
||||||
if (ref
|
if (ref
|
||||||
.read(feeSheetSessionCacheProvider)
|
.read(feeSheetSessionCacheProvider)
|
||||||
.average[amount] ==
|
.average[amount] ==
|
||||||
null) {
|
null) {
|
||||||
final manager = ref
|
final manager = ref
|
||||||
.read(walletsChangeNotifierProvider)
|
.read(walletsChangeNotifierProvider)
|
||||||
.getManager(walletId);
|
.getManager(walletId);
|
||||||
|
|
||||||
if (coin == Coin.monero || coin == Coin.wownero) {
|
if (coin == Coin.monero ||
|
||||||
final fee = await manager.estimateFeeFor(amount,
|
coin == Coin.wownero) {
|
||||||
MoneroTransactionPriority.regular.raw!);
|
final fee = await manager.estimateFeeFor(
|
||||||
ref
|
amount,
|
||||||
.read(feeSheetSessionCacheProvider)
|
MoneroTransactionPriority.regular.raw!);
|
||||||
.average[amount] = fee;
|
|
||||||
} else if ((coin == Coin.firo ||
|
|
||||||
coin == Coin.firoTestNet) &&
|
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(feeSheetSessionCacheProvider)
|
||||||
publicPrivateBalanceStateProvider
|
.average[amount] = fee;
|
||||||
.state)
|
} else if ((coin == Coin.firo ||
|
||||||
.state !=
|
coin == Coin.firoTestNet) &&
|
||||||
"Private") {
|
ref
|
||||||
ref
|
.read(
|
||||||
.read(feeSheetSessionCacheProvider)
|
publicPrivateBalanceStateProvider
|
||||||
.average[amount] =
|
.state)
|
||||||
await (manager.wallet as FiroWallet)
|
.state !=
|
||||||
.estimateFeeForPublic(amount, feeRate);
|
"Private") {
|
||||||
} else {
|
ref
|
||||||
ref
|
.read(feeSheetSessionCacheProvider)
|
||||||
.read(feeSheetSessionCacheProvider)
|
.average[amount] = await (manager.wallet
|
||||||
.average[amount] =
|
as FiroWallet)
|
||||||
await manager.estimateFeeFor(
|
.estimateFeeForPublic(amount, feeRate);
|
||||||
amount, feeRate);
|
} else {
|
||||||
|
ref
|
||||||
|
.read(feeSheetSessionCacheProvider)
|
||||||
|
.average[amount] =
|
||||||
|
await manager.estimateFeeFor(
|
||||||
|
amount, feeRate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return ref
|
||||||
return ref
|
.read(feeSheetSessionCacheProvider)
|
||||||
.read(feeSheetSessionCacheProvider)
|
.average[amount]!;
|
||||||
.average[amount]!;
|
},
|
||||||
},
|
isSelected: true,
|
||||||
isSelected: true,
|
);
|
||||||
);
|
} else {
|
||||||
} else {
|
return Row(
|
||||||
return Row(
|
children: [
|
||||||
|
AnimatedText(
|
||||||
|
stringsToLoopThrough: stringsToLoopThrough,
|
||||||
|
style: STextStyles.desktopTextExtraExtraSmall(
|
||||||
|
context)
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldActiveText,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: (coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
|
ref
|
||||||
|
.watch(
|
||||||
|
publicPrivateBalanceStateProvider.state)
|
||||||
|
.state ==
|
||||||
|
"Private"
|
||||||
|
? Text(
|
||||||
|
"~${ref.watch(pAmountFormatter(coin)).format(
|
||||||
|
Amount(
|
||||||
|
rawValue: BigInt.parse("3794"),
|
||||||
|
fractionDigits: coin.decimals,
|
||||||
|
),
|
||||||
|
indicatePrecisionLoss: false,
|
||||||
|
)}",
|
||||||
|
style: STextStyles.desktopTextExtraExtraSmall(context)
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldActiveText,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
AnimatedText(
|
Text(
|
||||||
stringsToLoopThrough: stringsToLoopThrough,
|
feeSelectionResult?.$2 ?? "",
|
||||||
style: STextStyles.desktopTextExtraExtraSmall(
|
style: STextStyles.desktopTextExtraExtraSmall(
|
||||||
context)
|
context)
|
||||||
.copyWith(
|
.copyWith(
|
||||||
|
@ -1514,36 +1542,21 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.textFieldActiveText,
|
.textFieldActiveText,
|
||||||
),
|
),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
feeSelectionResult?.$3 ?? "",
|
||||||
|
style: STextStyles.desktopTextExtraExtraSmall(
|
||||||
|
context)
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldActiveSearchIconRight,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
feeSelectionResult?.$2 ?? "",
|
|
||||||
style: STextStyles.desktopTextExtraExtraSmall(context)
|
|
||||||
.copyWith(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textFieldActiveText,
|
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.left,
|
),
|
||||||
),
|
|
||||||
Text(
|
|
||||||
feeSelectionResult?.$3 ?? "",
|
|
||||||
style: STextStyles.desktopTextExtraExtraSmall(context)
|
|
||||||
.copyWith(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textFieldActiveSearchIconRight,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (isCustomFee)
|
if (isCustomFee)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
|
|
@ -449,6 +449,15 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.value == null) {
|
if (response.value == null) {
|
||||||
|
if (response.exception != null &&
|
||||||
|
response.exception!.message
|
||||||
|
.contains("response is empty but status code is 200")) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"No ${tokenContract.name} transfers found for $addressString",
|
||||||
|
level: LogLevel.Info,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
throw response.exception ??
|
throw response.exception ??
|
||||||
Exception("Failed to fetch token transaction data");
|
Exception("Failed to fetch token transaction data");
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ class PriceAPI {
|
||||||
{required String baseCurrency}) async {
|
{required String baseCurrency}) async {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
if (_lastUsedBaseCurrency != baseCurrency ||
|
if (_lastUsedBaseCurrency != baseCurrency ||
|
||||||
now.difference(_lastCalled).inSeconds > 0) {
|
now.difference(_lastCalled) > refreshIntervalDuration) {
|
||||||
_lastCalled = now;
|
_lastCalled = now;
|
||||||
_lastUsedBaseCurrency = baseCurrency;
|
_lastUsedBaseCurrency = baseCurrency;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -157,20 +157,22 @@ class ThemeService {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// check installed version
|
// check installed version
|
||||||
final theme = ThemeService.instance.getTheme(themeId: "dark");
|
// final theme = ThemeService.instance.getTheme(themeId: "dark");
|
||||||
if ((theme?.version ?? 1) < _currentDefaultThemeVersion) {
|
// Force update theme to add missing icons for now
|
||||||
Logging.instance.log(
|
// TODO: uncomment if statement in future when themes are version 4 or above
|
||||||
"Updating default dark theme...",
|
// if ((theme?.version ?? 1) < _currentDefaultThemeVersion) {
|
||||||
level: LogLevel.Info,
|
Logging.instance.log(
|
||||||
);
|
"Updating default dark theme...",
|
||||||
final darkZip = await rootBundle.load("assets/default_themes/dark.zip");
|
level: LogLevel.Info,
|
||||||
await ThemeService.instance
|
);
|
||||||
.install(themeArchiveData: darkZip.buffer.asUint8List());
|
final darkZip = await rootBundle.load("assets/default_themes/dark.zip");
|
||||||
Logging.instance.log(
|
await ThemeService.instance
|
||||||
"Updating default dark theme... finished",
|
.install(themeArchiveData: darkZip.buffer.asUint8List());
|
||||||
level: LogLevel.Info,
|
Logging.instance.log(
|
||||||
);
|
"Updating default dark theme... finished",
|
||||||
}
|
level: LogLevel.Info,
|
||||||
|
);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,17 @@ class AddressUtils {
|
||||||
String address,
|
String address,
|
||||||
Map<String, String> params,
|
Map<String, String> params,
|
||||||
) {
|
) {
|
||||||
String uriString = "${coin.uriScheme}:$address";
|
// TODO: other sanitation as well ?
|
||||||
|
String sanitizedAddress = address;
|
||||||
|
if (coin == Coin.bitcoincash ||
|
||||||
|
coin == Coin.bitcoincashTestnet ||
|
||||||
|
coin == Coin.eCash) {
|
||||||
|
final prefix = "${coin.uriScheme}:";
|
||||||
|
if (address.startsWith(prefix)) {
|
||||||
|
sanitizedAddress = address.replaceFirst(prefix, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String uriString = "${coin.uriScheme}:$sanitizedAddress";
|
||||||
if (params.isNotEmpty) {
|
if (params.isNotEmpty) {
|
||||||
uriString += Uri(queryParameters: params).toString();
|
uriString += Uri(queryParameters: params).toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,15 @@ class AmountInputFormatter extends TextInputFormatter {
|
||||||
if (parts.length > 2) {
|
if (parts.length > 2) {
|
||||||
return oldValue;
|
return oldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final fractionDigits =
|
||||||
|
unit == null ? decimals : max(decimals - unit!.shift, 0);
|
||||||
|
|
||||||
if (newText.startsWith(decimalSeparator)) {
|
if (newText.startsWith(decimalSeparator)) {
|
||||||
|
if (newText.length - 1 > fractionDigits) {
|
||||||
|
newText = newText.substring(0, fractionDigits + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return TextEditingValue(
|
return TextEditingValue(
|
||||||
text: newText,
|
text: newText,
|
||||||
selection: TextSelection.collapsed(
|
selection: TextSelection.collapsed(
|
||||||
|
@ -54,28 +62,24 @@ class AmountInputFormatter extends TextInputFormatter {
|
||||||
fraction = "";
|
fraction = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
final fractionDigits =
|
|
||||||
unit == null ? decimals : max(decimals - unit!.shift, 0);
|
|
||||||
|
|
||||||
if (fraction.length > fractionDigits) {
|
if (fraction.length > fractionDigits) {
|
||||||
return oldValue;
|
fraction = fraction.substring(0, fractionDigits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newText.trim() == '' || newText.trim() == '0') {
|
String newString;
|
||||||
return newValue.copyWith(text: '');
|
final val = BigInt.tryParse(newText);
|
||||||
} else if (BigInt.parse(newText) < BigInt.one) {
|
if (val == null || val < BigInt.one) {
|
||||||
return newValue.copyWith(text: '');
|
newString = newText;
|
||||||
|
} else {
|
||||||
|
// insert group separator
|
||||||
|
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');
|
||||||
|
newString = newText.replaceAllMapped(
|
||||||
|
regex,
|
||||||
|
(m) => "${m.group(0)}${numberSymbols?.GROUP_SEP ?? ","}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert group separator
|
|
||||||
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');
|
|
||||||
|
|
||||||
String newString = newText.replaceAllMapped(
|
|
||||||
regex,
|
|
||||||
(m) => "${m.group(0)}${numberSymbols?.GROUP_SEP ?? ","}",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fraction != null) {
|
if (fraction != null) {
|
||||||
newString += decimalSeparator;
|
newString += decimalSeparator;
|
||||||
if (fraction.isNotEmpty) {
|
if (fraction.isNotEmpty) {
|
||||||
|
|
|
@ -65,8 +65,8 @@ class _EXCHANGE {
|
||||||
class _BUY {
|
class _BUY {
|
||||||
const _BUY();
|
const _BUY();
|
||||||
|
|
||||||
String simplexLogo(BuildContext context) {
|
String simplexLogo(Brightness themeBrightness) {
|
||||||
switch (MediaQuery.of(context).platformBrightness) {
|
switch (themeBrightness) {
|
||||||
case Brightness.dark:
|
case Brightness.dark:
|
||||||
return "assets/svg/buy/Simplex-Nuvei-Logo-light.svg";
|
return "assets/svg/buy/Simplex-Nuvei-Logo-light.svg";
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/widgets/animated_text.dart';
|
import 'package:stackwallet/widgets/animated_text.dart';
|
||||||
|
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
|
|
||||||
|
@ -234,6 +235,7 @@ class DesktopFeeItem extends ConsumerStatefulWidget {
|
||||||
required this.walletId,
|
required this.walletId,
|
||||||
required this.feeFor,
|
required this.feeFor,
|
||||||
required this.isSelected,
|
required this.isSelected,
|
||||||
|
this.isButton = true,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final FeeObject? feeObject;
|
final FeeObject? feeObject;
|
||||||
|
@ -246,6 +248,7 @@ class DesktopFeeItem extends ConsumerStatefulWidget {
|
||||||
required Coin coin,
|
required Coin coin,
|
||||||
}) feeFor;
|
}) feeFor;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
|
final bool isButton;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<DesktopFeeItem> createState() => _DesktopFeeItemState();
|
ConsumerState<DesktopFeeItem> createState() => _DesktopFeeItemState();
|
||||||
|
@ -291,19 +294,50 @@ class _DesktopFeeItemState extends ConsumerState<DesktopFeeItem> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
debugPrint("BUILD: $runtimeType : ${widget.feeRateType}");
|
debugPrint("BUILD: $runtimeType : ${widget.feeRateType}");
|
||||||
|
|
||||||
return MaterialButton(
|
return ConditionalParent(
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
condition: widget.isButton,
|
||||||
onPressed: () {
|
builder: (child) => MaterialButton(
|
||||||
Navigator.of(context).pop(
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
(
|
onPressed: () {
|
||||||
widget.feeRateType,
|
Navigator.of(context).pop(
|
||||||
feeString,
|
(
|
||||||
timeString,
|
widget.feeRateType,
|
||||||
),
|
feeString,
|
||||||
);
|
timeString,
|
||||||
},
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
|
if (!widget.isButton) {
|
||||||
|
final coin = ref.watch(
|
||||||
|
walletsChangeNotifierProvider.select(
|
||||||
|
(value) => value.getManager(widget.walletId).coin,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
|
ref.watch(publicPrivateBalanceStateProvider.state).state ==
|
||||||
|
"Private") {
|
||||||
|
return Text(
|
||||||
|
"~${ref.watch(pAmountFormatter(coin)).format(
|
||||||
|
Amount(
|
||||||
|
rawValue: BigInt.parse("3794"),
|
||||||
|
fractionDigits: coin.decimals,
|
||||||
|
),
|
||||||
|
indicatePrecisionLoss: false,
|
||||||
|
)}",
|
||||||
|
style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldActiveText,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (widget.feeRateType == FeeRateType.custom) {
|
if (widget.feeRateType == FeeRateType.custom) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
|
|
@ -26,6 +26,7 @@ import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
|
||||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
import 'package:stackwallet/utilities/show_loading.dart';
|
import 'package:stackwallet/utilities/show_loading.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||||
|
@ -136,17 +137,18 @@ class SimpleWalletCard extends ConsumerWidget {
|
||||||
context: desktopNavigatorState?.context ?? context,
|
context: desktopNavigatorState?.context ?? context,
|
||||||
opaqueBG: true,
|
opaqueBG: true,
|
||||||
message: "Loading ${contract.name}",
|
message: "Loading ${contract.name}",
|
||||||
|
isDesktop: Util.isDesktop,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
// TODO: show error dialog here?
|
||||||
|
Logging.instance.log(
|
||||||
|
"Failed to load token wallet for $contract",
|
||||||
|
level: LogLevel.Error,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desktopNavigatorState == null) {
|
|
||||||
// pop loading
|
|
||||||
nav.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desktopNavigatorState != null) {
|
if (desktopNavigatorState != null) {
|
||||||
await desktopNavigatorState!.pushNamed(
|
await desktopNavigatorState!.pushNamed(
|
||||||
DesktopTokenView.routeName,
|
DesktopTokenView.routeName,
|
||||||
|
|
Loading…
Reference in a new issue