mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-21 06:38:52 +00:00
buy quote preview view and sample quote class
This commit is contained in:
parent
0c9dcf6403
commit
650ae9fe09
8 changed files with 277 additions and 5 deletions
9
assets/svg/buy/Simplex-Nuvei-Logo.svg
Normal file
9
assets/svg/buy/Simplex-Nuvei-Logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
25
lib/models/buy/response_objects/quote.dart
Normal file
25
lib/models/buy/response_objects/quote.dart
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import 'package:decimal/decimal.dart';
|
||||||
|
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||||
|
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
||||||
|
|
||||||
|
class SimplexQuote {
|
||||||
|
// todo: this class
|
||||||
|
|
||||||
|
final Crypto crypto;
|
||||||
|
final Fiat fiat;
|
||||||
|
|
||||||
|
final Decimal youPayFiatPrice;
|
||||||
|
final Decimal youReceiveCryptoAmount;
|
||||||
|
|
||||||
|
final String purchaseId;
|
||||||
|
final String receivingAddress;
|
||||||
|
|
||||||
|
SimplexQuote({
|
||||||
|
required this.crypto,
|
||||||
|
required this.fiat,
|
||||||
|
required this.youPayFiatPrice,
|
||||||
|
required this.youReceiveCryptoAmount,
|
||||||
|
required this.purchaseId,
|
||||||
|
required this.receivingAddress,
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,12 +1,15 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.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/crypto.dart';
|
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||||
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
||||||
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||||
import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
|
import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
|
||||||
|
import 'package:stackwallet/pages/buy_view/buy_quote_preview.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
|
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart';
|
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_selection_view.dart';
|
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_selection_view.dart';
|
||||||
|
@ -814,10 +817,24 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
||||||
),
|
),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
buttonHeight: isDesktop ? ButtonHeight.l : null,
|
buttonHeight: isDesktop ? ButtonHeight.l : null,
|
||||||
enabled: ref.watch(exchangeFormStateProvider
|
enabled: _receiveAddressController.text.isNotEmpty &&
|
||||||
.select((value) => value.canExchange)),
|
_buyAmountController.text.isNotEmpty,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// preview buy quote
|
// preview buy quote
|
||||||
|
// TODO: show loading while fetching quote
|
||||||
|
final quote = SimplexQuote(
|
||||||
|
crypto: selectedCrypto!,
|
||||||
|
fiat: selectedFiat!,
|
||||||
|
youPayFiatPrice: Decimal.parse("100"),
|
||||||
|
youReceiveCryptoAmount: Decimal.parse("1.0238917"),
|
||||||
|
purchaseId: "someID",
|
||||||
|
receivingAddress: _receiveAddressController.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
BuyQuotePreviewView.routeName,
|
||||||
|
arguments: quote,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
label: "Preview quote",
|
label: "Preview quote",
|
||||||
)
|
)
|
||||||
|
|
197
lib/pages/buy_view/buy_quote_preview.dart
Normal file
197
lib/pages/buy_view/buy_quote_preview.dart
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
import 'package:stackwallet/widgets/background.dart';
|
||||||
|
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||||
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
class BuyQuotePreviewView extends StatefulWidget {
|
||||||
|
const BuyQuotePreviewView({
|
||||||
|
Key? key,
|
||||||
|
required this.quote,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final SimplexQuote quote;
|
||||||
|
|
||||||
|
static const String routeName = "/buyQuotePreview";
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<BuyQuotePreviewView> createState() => _BuyQuotePreviewViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BuyQuotePreviewViewState extends State<BuyQuotePreviewView> {
|
||||||
|
final isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
|
Future<void> _buy() async {
|
||||||
|
// do buy/redirect to simplex page
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ConditionalParent(
|
||||||
|
condition: !isDesktop,
|
||||||
|
builder: (child) {
|
||||||
|
return Background(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.backgroundAppBar,
|
||||||
|
leading: const AppBarBackButton(),
|
||||||
|
title: Text(
|
||||||
|
"Preview quote",
|
||||||
|
style: STextStyles.navBarTitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: LayoutBuilder(
|
||||||
|
builder: (builderContext, constraints) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 12,
|
||||||
|
top: 12,
|
||||||
|
right: 12,
|
||||||
|
),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: constraints.maxHeight - 24,
|
||||||
|
),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Buy ${widget.quote.crypto.ticker.toUpperCase()}",
|
||||||
|
style: STextStyles.pageTitleH1(context),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"You pay",
|
||||||
|
style: STextStyles.label(context),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"${widget.quote.youPayFiatPrice.toStringAsFixed(2)} ${widget.quote.fiat.ticker.toUpperCase()}",
|
||||||
|
style: STextStyles.label(context).copyWith(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.textDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"You receive",
|
||||||
|
style: STextStyles.label(context),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"${widget.quote.youReceiveCryptoAmount} ${widget.quote.crypto.ticker.toUpperCase()}",
|
||||||
|
style: STextStyles.label(context).copyWith(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.textDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Receiving ${widget.quote.crypto.ticker.toUpperCase()} address",
|
||||||
|
style: STextStyles.label(context),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"${widget.quote.receivingAddress} ",
|
||||||
|
style: STextStyles.label(context).copyWith(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.textDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Purchase ID",
|
||||||
|
style: STextStyles.label(context),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
widget.quote.purchaseId,
|
||||||
|
style: STextStyles.label(context).copyWith(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.textDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Provider",
|
||||||
|
style: STextStyles.label(context),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 64,
|
||||||
|
child: SvgPicture.asset(Assets.buy.simplexLogo),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
PrimaryButton(
|
||||||
|
label: "Buy",
|
||||||
|
onPressed: _buy,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,8 @@ class _ConfirmChangeNowSendViewState
|
||||||
late final String routeOnSuccessName;
|
late final String routeOnSuccessName;
|
||||||
late final Trade trade;
|
late final Trade trade;
|
||||||
|
|
||||||
|
final isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
Future<void> _attemptSend(BuildContext context) async {
|
Future<void> _attemptSend(BuildContext context) async {
|
||||||
unawaited(
|
unawaited(
|
||||||
showDialog<void>(
|
showDialog<void>(
|
||||||
|
@ -227,8 +229,6 @@ class _ConfirmChangeNowSendViewState
|
||||||
final managerProvider = ref.watch(walletsChangeNotifierProvider
|
final managerProvider = ref.watch(walletsChangeNotifierProvider
|
||||||
.select((value) => value.getManagerProvider(walletId)));
|
.select((value) => value.getManagerProvider(walletId)));
|
||||||
|
|
||||||
final isDesktop = Util.isDesktop;
|
|
||||||
|
|
||||||
return ConditionalParent(
|
return ConditionalParent(
|
||||||
condition: !isDesktop,
|
condition: !isDesktop,
|
||||||
builder: (child) {
|
builder: (child) {
|
||||||
|
@ -238,7 +238,7 @@ class _ConfirmChangeNowSendViewState
|
||||||
Theme.of(context).extension<StackColors>()!.background,
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).extension<StackColors>()!.background,
|
Theme.of(context).extension<StackColors>()!.backgroundAppBar,
|
||||||
leading: AppBarBackButton(
|
leading: AppBarBackButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
// if (FocusScope.of(context).hasFocus) {
|
// if (FocusScope.of(context).hasFocus) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||||
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
|
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
|
||||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||||
|
@ -22,6 +23,7 @@ import 'package:stackwallet/pages/address_book_views/subviews/address_book_filte
|
||||||
import 'package:stackwallet/pages/address_book_views/subviews/contact_details_view.dart';
|
import 'package:stackwallet/pages/address_book_views/subviews/contact_details_view.dart';
|
||||||
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
|
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
|
||||||
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
|
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
|
||||||
|
import 'package:stackwallet/pages/buy_view/buy_quote_preview.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
|
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart';
|
import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/exchange_loading_overlay.dart';
|
import 'package:stackwallet/pages/exchange_view/exchange_loading_overlay.dart';
|
||||||
|
@ -1001,6 +1003,20 @@ class RouteGenerator {
|
||||||
}
|
}
|
||||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
|
case BuyQuotePreviewView.routeName:
|
||||||
|
if (args is SimplexQuote) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => BuyQuotePreviewView(
|
||||||
|
quote: args,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
// == Desktop specific routes ============================================
|
// == Desktop specific routes ============================================
|
||||||
case CreatePasswordView.routeName:
|
case CreatePasswordView.routeName:
|
||||||
if (args is bool) {
|
if (args is bool) {
|
||||||
|
|
|
@ -31,7 +31,12 @@ class _EXCHANGE {
|
||||||
class _BUY {
|
class _BUY {
|
||||||
const _BUY();
|
const _BUY();
|
||||||
|
|
||||||
|
// TODO: switch this to something like
|
||||||
|
// String buy(BuildContext context) =>
|
||||||
|
// "assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/buy.svg";
|
||||||
String get buy => "assets/svg/light/buy-coins-icon.svg";
|
String get buy => "assets/svg/light/buy-coins-icon.svg";
|
||||||
|
|
||||||
|
String get simplexLogo => "assets/svg/buy/Simplex-Nuvei-Logo.svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SVG {
|
class _SVG {
|
||||||
|
|
|
@ -384,6 +384,9 @@ flutter:
|
||||||
- assets/svg/oceanBreeze/buy-coins-icon.svg
|
- assets/svg/oceanBreeze/buy-coins-icon.svg
|
||||||
- assets/svg/oceanBreeze/bg.svg
|
- assets/svg/oceanBreeze/bg.svg
|
||||||
|
|
||||||
|
# buy
|
||||||
|
- assets/svg/buy/Simplex-Nuvei-Logo.svg
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
# For details regarding adding assets from package dependencies, see
|
# For details regarding adding assets from package dependencies, see
|
||||||
|
|
Loading…
Reference in a new issue