Merge remote-tracking branch 'origin/staging' into paynyms

This commit is contained in:
julian 2023-01-27 18:28:53 -06:00
commit 32c942ad42
3 changed files with 126 additions and 34 deletions

View file

@ -98,9 +98,11 @@ class _BuyFormState extends ConsumerState<BuyForm> {
bool _hovering1 = false;
bool _hovering2 = false;
// TODO actually check USD min and max, these could get updated by Simplex
static Decimal minFiat = Decimal.fromInt(50);
static Decimal maxFiat = Decimal.fromInt(20000);
// We can't get crypto min and max without asking for a quote
static Decimal minCrypto = Decimal.parse((0.00000001)
.toString()); // lol how to go from double->Decimal more easily?
static Decimal maxCrypto = Decimal.parse((10000.00000000).toString());
@ -476,8 +478,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
} else {
return StackDialog(
title: "Simplex API error",
message:
"${quoteResponse.exception?.errorMessage.substring(19, quoteResponse.exception?.errorMessage?.length ?? 109 - (14 + 19))}",
message: "${quoteResponse.exception?.errorMessage}",
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
@ -501,10 +502,10 @@ class _BuyFormState extends ConsumerState<BuyForm> {
} else {
// Error; probably amount out of bounds
String errorMessage = "${quoteResponse.exception?.errorMessage}";
if (errorMessage.contains('must be between')) {
errorMessage = errorMessage.substring(
(errorMessage.indexOf('getQuote exception: ') ?? 19) + 20,
errorMessage.indexOf(", value: null"));
if (errorMessage.contains('must be between')) {
_BuyFormState.boundedCryptoTicker = errorMessage.substring(
errorMessage.indexOf('The ') + 4,
errorMessage.indexOf(' amount must be between'));
@ -565,7 +566,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
} else {
return StackDialog(
title: "Simplex API error",
message: errorMessage,
message: "${quoteResponse.exception?.errorMessage}",
// "${quoteResponse.exception?.errorMessage.substring(8, (quoteResponse.exception?.errorMessage?.length ?? 109) - (8 + 6))}",
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
@ -936,7 +938,10 @@ class _BuyFormState extends ConsumerState<BuyForm> {
color: Theme.of(context).extension<StackColors>()!.textDark,
),
key: const Key("buyAmountInputFieldTextFieldKey"),
controller: _buyAmountController..text = '50.00',
controller: _buyAmountController
..text = _BuyFormState.buyWithFiat
? _BuyFormState.minFiat.toStringAsFixed(2) ?? '50.00'
: _BuyFormState.minCrypto.toStringAsFixed(8),
focusNode: _buyAmountFocusNode,
keyboardType: Util.isDesktop
? null
@ -1016,11 +1021,20 @@ class _BuyFormState extends ConsumerState<BuyForm> {
_buyAmountController.text.isNotEmpty
? TextFieldIconButton(
key: const Key(
"buyViewClearAddressFieldButtonKey"),
"buyViewClearAmountFieldButtonKey"),
onTap: () {
_buyAmountController.text = "";
// _receiveAddress = "";
setState(() {});
if (_BuyFormState.buyWithFiat) {
_buyAmountController.text = _BuyFormState
.minFiat
.toStringAsFixed(2);
} else {
if (selectedCrypto?.ticker ==
_BuyFormState.boundedCryptoTicker) {
_buyAmountController.text = _BuyFormState
.minCrypto
.toStringAsFixed(8);
}
}
},
child: const XIcon(),
)
@ -1366,8 +1380,10 @@ class NumericalRangeFormatter extends TextInputFormatter {
TextEditingValue oldValue,
TextEditingValue newValue,
) {
final TextSelection newSelection = newValue.selection;
String newVal = newValue.text;
TextSelection newSelection = newValue.selection;
String newVal = _BuyFormState.buyWithFiat
? Decimal.parse(newValue.text).toStringAsFixed(2)
: Decimal.parse(newValue.text).toStringAsFixed(8);
if (newValue.text == '') {
return newValue;
} else {
@ -1398,7 +1414,7 @@ class NumericalRangeFormatter extends TextInputFormatter {
: r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$';
// return RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
return RegExp(regexString).hasMatch(newValue.text)
return RegExp(regexString).hasMatch(newVal)
? TextEditingValue(text: newVal, selection: newSelection)
: oldValue;
}

View file

@ -29,18 +29,9 @@ class BuyWarningPopup extends StatelessWidget {
SimplexOrder? order;
Future<BuyResponse<SimplexOrder>> newOrder(SimplexQuote quote) async {
final response = await SimplexAPI.instance.newOrder(quote);
final orderResponse = await SimplexAPI.instance.newOrder(quote);
// if (response.value != null) {
// ref.read(simplexProvider).updateOrder(response.value!);
// } else {
// Logging.instance.log(
// "_loadQuote: $response",
// level: LogLevel.Warning,
// );
// }
return response;
return orderResponse;
}
Future<BuyResponse<bool>> redirect(SimplexOrder order) async {
@ -122,13 +113,90 @@ class BuyWarningPopup extends StatelessWidget {
rightButton: PrimaryButton(
label: "Continue",
onPressed: () async {
BuyResponse<SimplexOrder> order = await newOrder(quote);
await redirect(order.value as SimplexOrder).then((_response) async {
this.order = order.value as SimplexOrder;
BuyResponse<SimplexOrder> orderResponse = await newOrder(quote);
if (orderResponse.exception == null) {
await redirect(orderResponse.value as SimplexOrder)
.then((_response) async {
this.order = orderResponse.value as SimplexOrder;
Navigator.of(context, rootNavigator: isDesktop).pop();
Navigator.of(context, rootNavigator: isDesktop).pop();
await _buyInvoice();
});
} else {
await showDialog<dynamic>(
context: context,
barrierDismissible: true,
builder: (context) {
if (isDesktop) {
return DesktopDialog(
maxWidth: 450,
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Simplex API error",
style: STextStyles.desktopH3(context),
),
const SizedBox(
height: 24,
),
Text(
"${orderResponse.exception?.errorMessage}",
style: STextStyles.smallMed14(context),
),
const SizedBox(
height: 56,
),
Row(
children: [
const Spacer(),
Expanded(
child: PrimaryButton(
buttonHeight: ButtonHeight.l,
label: "Ok",
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pop(); // weee
},
),
),
],
)
],
),
),
);
} else {
return StackDialog(
title: "Simplex API error",
message: "${orderResponse.exception?.errorMessage}",
// "${quoteResponse.exception?.errorMessage.substring(8, (quoteResponse.exception?.errorMessage?.length ?? 109) - (8 + 6))}",
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonStyle(context),
child: Text(
"Ok",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pop(); // weee
},
),
);
}
},
);
}
},
),
icon: SizedBox(

View file

@ -16,7 +16,7 @@ import 'package:url_launcher/url_launcher.dart';
class SimplexAPI {
static const String authority = "simplex-sandbox.stackwallet.com";
// static const String authority = "localhost";
// static const String authority = "localhost"; // For development purposes
static const String scheme = authority == "localhost" ? "http" : "https";
final _prefs = Prefs.instance;
@ -188,8 +188,11 @@ class SimplexAPI {
}
final jsonArray = jsonDecode(res.body);
if (jsonArray.containsKey('error') as bool) {
if (jsonArray['error'] == true || jsonArray['error'] == 'true') {
// jsonArray['error'] as bool == true?
throw Exception('getQuote exception: ${jsonArray['error']}');
}
}
jsonArray['quote'] = quote; // Add and pass this on
@ -273,6 +276,11 @@ class SimplexAPI {
throw Exception('newOrder exception: statusCode= ${res.statusCode}');
}
final jsonArray = jsonDecode(res.body); // TODO check if valid json
if (jsonArray.containsKey('error') as bool) {
if (jsonArray['error'] == true || jsonArray['error'] == 'true') {
throw Exception(jsonArray['message']);
}
}
SimplexOrder _order = SimplexOrder(
quote: quote,