diff --git a/assets/svg/share-2.svg b/assets/svg/share-2.svg
new file mode 100644
index 000000000..d002d2bff
--- /dev/null
+++ b/assets/svg/share-2.svg
@@ -0,0 +1,14 @@
+
diff --git a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart
index a473d0d45..037677a40 100644
--- a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart
+++ b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart
@@ -6,10 +6,12 @@ import 'dart:ui' as ui;
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
+import 'package:flutter_svg/svg.dart';
import 'package:path_provider/path_provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:share_plus/share_plus.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
@@ -318,8 +320,7 @@ class _GenerateUriQrCodeViewState extends State {
child: QrImage(
data: uriString,
size: width,
- backgroundColor:
- CFColors.almostWhite,
+ backgroundColor: CFColors.white,
foregroundColor:
CFColors.stackAccent,
),
@@ -344,12 +345,40 @@ class _GenerateUriQrCodeViewState extends State {
CFColors.buttonGray,
),
),
- child: Text(
- "Share",
- style:
- STextStyles.button.copyWith(
- color: CFColors.stackAccent,
- ),
+ child: Row(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ crossAxisAlignment:
+ CrossAxisAlignment.center,
+ children: [
+ Center(
+ child: SvgPicture.asset(
+ Assets.svg.share,
+ width: 14,
+ height: 14,
+ ),
+ ),
+ const SizedBox(
+ width: 4,
+ ),
+ Column(
+ children: [
+ Text(
+ "Share",
+ textAlign:
+ TextAlign.center,
+ style: STextStyles.button
+ .copyWith(
+ color: CFColors
+ .stackAccent,
+ ),
+ ),
+ const SizedBox(
+ height: 2,
+ ),
+ ],
+ ),
+ ],
),
),
),
diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart
index 4662abac2..b0f49682b 100644
--- a/lib/pages/receive_view/receive_view.dart
+++ b/lib/pages/receive_view/receive_view.dart
@@ -1,36 +1,114 @@
+import 'dart:async';
+
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart';
+import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
-import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+import 'package:stackwallet/widgets/custom_loading_overlay.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
-class ReceiveView extends StatelessWidget {
+class ReceiveView extends ConsumerStatefulWidget {
const ReceiveView({
Key? key,
required this.coin,
- required this.receivingAddress,
+ required this.walletId,
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
static const String routeName = "/receiveView";
final Coin coin;
- final String receivingAddress;
+ final String walletId;
final ClipboardInterface clipboard;
+ @override
+ ConsumerState createState() => _ReceiveViewState();
+}
+
+class _ReceiveViewState extends ConsumerState {
+ late final Coin coin;
+ late final String walletId;
+ late final ClipboardInterface clipboard;
+
+ Future generateNewAddress() async {
+ bool shouldPop = false;
+ unawaited(
+ showDialog(
+ context: context,
+ builder: (_) {
+ return WillPopScope(
+ onWillPop: () async => shouldPop,
+ child: const CustomLoadingOverlay(
+ message: "Generating address",
+ eventBus: null,
+ ),
+ );
+ },
+ ),
+ );
+
+ await ref
+ .read(walletsChangeNotifierProvider)
+ .getManager(walletId)
+ .generateNewAddress();
+
+ shouldPop = true;
+
+ if (mounted) {
+ Navigator.of(context)
+ .popUntil(ModalRoute.withName(ReceiveView.routeName));
+ }
+ }
+
+ String receivingAddress = "";
+
+ @override
+ void initState() {
+ walletId = widget.walletId;
+ coin = widget.coin;
+ clipboard = widget.clipboard;
+
+ WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
+ final address = await ref
+ .read(walletsChangeNotifierProvider)
+ .getManager(walletId)
+ .currentReceivingAddress;
+ setState(() {
+ receivingAddress = address;
+ });
+ });
+
+ super.initState();
+ }
+
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
+
+ ref.listen(
+ ref
+ .read(walletsChangeNotifierProvider)
+ .getManagerProvider(walletId)
+ .select((value) => value.currentReceivingAddress),
+ (previous, next) {
+ if (next is Future) {
+ next.then((value) => setState(() => receivingAddress = value));
+ }
+ });
+
return Scaffold(
backgroundColor: CFColors.almostWhite,
appBar: AppBar(
@@ -52,15 +130,19 @@ class ReceiveView extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- Container(
- decoration: BoxDecoration(
- color: CFColors.white,
- borderRadius: BorderRadius.circular(
- Constants.size.circularBorderRadius,
- ),
- ),
- child: Padding(
- padding: const EdgeInsets.all(12.0),
+ GestureDetector(
+ onTap: () {
+ clipboard.setData(
+ ClipboardData(text: receivingAddress),
+ );
+ showFloatingFlushBar(
+ type: FlushBarType.info,
+ message: "Copied to clipboard",
+ iconAsset: Assets.svg.copy,
+ context: context,
+ );
+ },
+ child: RoundedWhiteContainer(
child: Column(
children: [
Row(
@@ -70,35 +152,22 @@ class ReceiveView extends StatelessWidget {
style: STextStyles.itemSubtitle,
),
const Spacer(),
- GestureDetector(
- onTap: () {
- clipboard.setData(
- ClipboardData(text: receivingAddress),
- );
- showFloatingFlushBar(
- type: FlushBarType.info,
- message: "Copied to clipboard",
- iconAsset: Assets.svg.copy,
- context: context,
- );
- },
- child: Row(
- children: [
- SvgPicture.asset(
- Assets.svg.copy,
- width: 10,
- height: 10,
- color: CFColors.link2,
- ),
- const SizedBox(
- width: 4,
- ),
- Text(
- "Copy",
- style: STextStyles.link2,
- ),
- ],
- ),
+ Row(
+ children: [
+ SvgPicture.asset(
+ Assets.svg.copy,
+ width: 10,
+ height: 10,
+ color: CFColors.link2,
+ ),
+ const SizedBox(
+ width: 4,
+ ),
+ Text(
+ "Copy",
+ style: STextStyles.link2,
+ ),
+ ],
),
],
),
@@ -119,47 +188,62 @@ class ReceiveView extends StatelessWidget {
),
),
),
- const SizedBox(
- height: 30,
- ),
- Center(
- child: QrImage(
- data: "${coin.uriScheme}:$receivingAddress",
- size: MediaQuery.of(context).size.width / 2,
- foregroundColor: CFColors.stackAccent,
+ if (coin != Coin.epicCash)
+ const SizedBox(
+ height: 12,
),
- ),
- const SizedBox(
- height: 30,
- ),
- // Spacer(
- // flex: 7,
- // ),
- TextButton(
- onPressed: () {
- Navigator.of(context).push(
- RouteGenerator.getRoute(
- shouldUseMaterialRoute:
- RouteGenerator.useMaterialPageRoute,
- builder: (_) => GenerateUriQrCodeView(
- coin: coin,
- receivingAddress: receivingAddress,
- ),
- settings: const RouteSettings(
- name: GenerateUriQrCodeView.routeName,
- ),
+ if (coin != Coin.epicCash)
+ TextButton(
+ onPressed: generateNewAddress,
+ style: ButtonStyle(
+ backgroundColor: MaterialStateProperty.all(
+ CFColors.buttonGray,
+ ),
+ ),
+ child: Text(
+ "Generate new address",
+ style: STextStyles.button.copyWith(
+ color: CFColors.stackAccent,
),
- );
- },
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.all(
- CFColors.buttonGray,
),
),
- child: Text(
- "Generate QR Code",
- style: STextStyles.button.copyWith(
- color: CFColors.stackAccent,
+ const SizedBox(
+ height: 30,
+ ),
+ RoundedWhiteContainer(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Center(
+ child: Column(
+ children: [
+ QrImage(
+ data: "${coin.uriScheme}:$receivingAddress",
+ size: MediaQuery.of(context).size.width / 2,
+ foregroundColor: CFColors.stackAccent,
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ BlueTextButton(
+ text: "Create new QR code",
+ onTap: () async {
+ unawaited(Navigator.of(context).push(
+ RouteGenerator.getRoute(
+ shouldUseMaterialRoute:
+ RouteGenerator.useMaterialPageRoute,
+ builder: (_) => GenerateUriQrCodeView(
+ coin: coin,
+ receivingAddress: receivingAddress,
+ ),
+ settings: const RouteSettings(
+ name: GenerateUriQrCodeView.routeName,
+ ),
+ ),
+ ));
+ },
+ ),
+ ],
+ ),
),
),
),
diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart
index 3f097ddf3..198e30904 100644
--- a/lib/pages/wallet_view/wallet_view.dart
+++ b/lib/pages/wallet_view/wallet_view.dart
@@ -532,19 +532,17 @@ class _WalletViewState extends ConsumerState {
onExchangePressed: () =>
_onExchangePressed(context),
onReceivePressed: () async {
- final address = await ref
- .read(managerProvider)
- .currentReceivingAddress;
final coin =
ref.read(managerProvider).coin;
if (mounted) {
- Navigator.of(context).pushNamed(
+ unawaited(
+ Navigator.of(context).pushNamed(
ReceiveView.routeName,
arguments: Tuple2(
- address,
+ walletId,
coin,
),
- );
+ ));
}
},
onSendPressed: () {
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index 329018d9a..001c21b0d 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -681,7 +681,7 @@ class RouteGenerator {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => ReceiveView(
- receivingAddress: args.item1,
+ walletId: args.item1,
coin: args.item2,
),
settings: RouteSettings(
diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart
index 0750e9b93..342fb7b91 100644
--- a/lib/services/coins/bitcoin/bitcoin_wallet.dart
+++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart
@@ -3825,4 +3825,34 @@ class BitcoinWallet extends CoinServiceAPI {
return available - estimatedFee;
}
+
+ @override
+ Future generateNewAddress() async {
+ try {
+ await _incrementAddressIndexForChain(
+ 0, DerivePathType.bip84); // First increment the receiving index
+ final newReceivingIndex = DB.instance.get(
+ boxName: walletId,
+ key: 'receivingIndexP2WPKH') as int; // Check the new receiving index
+ final newReceivingAddress = await _generateAddressForChain(
+ 0,
+ newReceivingIndex,
+ DerivePathType
+ .bip84); // Use new index to derive a new receiving address
+ await _addToAddressesArrayForChain(
+ newReceivingAddress,
+ 0,
+ DerivePathType
+ .bip84); // Add that new receiving address to the array of receiving addresses
+ _currentReceivingAddress = Future(() =>
+ newReceivingAddress); // Set the new receiving address that the service
+
+ return true;
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from generateNewAddress(): $e\n$s",
+ level: LogLevel.Error);
+ return false;
+ }
+ }
}
diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart
index 3d8b1bd10..bc0e4be28 100644
--- a/lib/services/coins/coin_service.dart
+++ b/lib/services/coins/coin_service.dart
@@ -212,4 +212,6 @@ abstract class CoinServiceAPI {
bool get isConnected;
Future estimateFeeFor(int satoshiAmount, int feeRate);
+
+ Future generateNewAddress();
}
diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart
index 7a3a70a96..a7b2132ad 100644
--- a/lib/services/coins/dogecoin/dogecoin_wallet.dart
+++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart
@@ -3011,6 +3011,35 @@ class DogecoinWallet extends CoinServiceAPI {
return available - estimatedFee;
}
+
+ Future generateNewAddress() async {
+ try {
+ await _incrementAddressIndexForChain(
+ 0, DerivePathType.bip44); // First increment the receiving index
+ final newReceivingIndex = DB.instance.get(
+ boxName: walletId,
+ key: 'receivingIndexP2PKH') as int; // Check the new receiving index
+ final newReceivingAddress = await _generateAddressForChain(
+ 0,
+ newReceivingIndex,
+ DerivePathType
+ .bip44); // Use new index to derive a new receiving address
+ await _addToAddressesArrayForChain(
+ newReceivingAddress,
+ 0,
+ DerivePathType
+ .bip44); // Add that new receiving address to the array of receiving addresses
+ _currentReceivingAddressP2PKH = Future(() =>
+ newReceivingAddress); // Set the new receiving address that the service
+
+ return true;
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from generateNewAddress(): $e\n$s",
+ level: LogLevel.Error);
+ return false;
+ }
+ }
}
// Dogecoin Network
diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart
index a99718dd3..514ddb79f 100644
--- a/lib/services/coins/epiccash/epiccash_wallet.dart
+++ b/lib/services/coins/epiccash/epiccash_wallet.dart
@@ -2306,4 +2306,29 @@ class EpicCashWallet extends CoinServiceAPI {
// TODO: implement this
return currentFee;
}
+
+ // not used in epic currently
+ @override
+ Future generateNewAddress() async {
+ try {
+ // await incrementAddressIndexForChain(
+ // 0); // First increment the receiving index
+ // final newReceivingIndex =
+ // DB.instance.get(boxName: walletId, key: 'receivingIndex')
+ // as int; // Check the new receiving index
+ // final newReceivingAddress = await _generateAddressForChain(0,
+ // newReceivingIndex); // Use new index to derive a new receiving address
+ // await addToAddressesArrayForChain(newReceivingAddress,
+ // 0); // Add that new receiving address to the array of receiving addresses
+ // _currentReceivingAddress = Future(() =>
+ // newReceivingAddress); // Set the new receiving address that the service
+
+ return true;
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from generateNewAddress(): $e\n$s",
+ level: LogLevel.Error);
+ return false;
+ }
+ }
}
diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart
index c8bd9be24..4108cce39 100644
--- a/lib/services/coins/firo/firo_wallet.dart
+++ b/lib/services/coins/firo/firo_wallet.dart
@@ -3857,4 +3857,28 @@ class FiroWallet extends CoinServiceAPI {
rethrow;
}
}
+
+ @override
+ Future generateNewAddress() async {
+ try {
+ await incrementAddressIndexForChain(
+ 0); // First increment the receiving index
+ final newReceivingIndex =
+ DB.instance.get(boxName: walletId, key: 'receivingIndex')
+ as int; // Check the new receiving index
+ final newReceivingAddress = await _generateAddressForChain(0,
+ newReceivingIndex); // Use new index to derive a new receiving address
+ await addToAddressesArrayForChain(newReceivingAddress,
+ 0); // Add that new receiving address to the array of receiving addresses
+ _currentReceivingAddress = Future(() =>
+ newReceivingAddress); // Set the new receiving address that the service
+
+ return true;
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from generateNewAddress(): $e\n$s",
+ level: LogLevel.Error);
+ return false;
+ }
+ }
}
diff --git a/lib/services/coins/manager.dart b/lib/services/coins/manager.dart
index 659db73bd..c8329ec28 100644
--- a/lib/services/coins/manager.dart
+++ b/lib/services/coins/manager.dart
@@ -266,4 +266,12 @@ class Manager with ChangeNotifier {
Future estimateFeeFor(int satoshiAmount, int feeRate) async {
return _currentWallet.estimateFeeFor(satoshiAmount, feeRate);
}
+
+ Future generateNewAddress() async {
+ final success = await _currentWallet.generateNewAddress();
+ if (success) {
+ notifyListeners();
+ }
+ return success;
+ }
}
diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart
index 95794a356..b63e711a4 100644
--- a/lib/services/coins/monero/monero_wallet.dart
+++ b/lib/services/coins/monero/monero_wallet.dart
@@ -1521,4 +1521,33 @@ class MoneroWallet extends CoinServiceAPI {
10000;
return fee;
}
+
+ @override
+ Future generateNewAddress() async {
+ try {
+ const String indexKey = "receivingIndex";
+ // First increment the receiving index
+ await _incrementAddressIndexForChain(0);
+ final newReceivingIndex =
+ DB.instance.get(boxName: walletId, key: indexKey) as int;
+
+ // Use new index to derive a new receiving address
+ final newReceivingAddress =
+ await _generateAddressForChain(0, newReceivingIndex);
+
+ // Add that new receiving address to the array of receiving addresses
+ await _addToAddressesArrayForChain(newReceivingAddress, 0);
+
+ // Set the new receiving address that the service
+
+ _currentReceivingAddress = Future(() => newReceivingAddress);
+
+ return true;
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from generateNewAddress(): $e\n$s",
+ level: LogLevel.Error);
+ return false;
+ }
+ }
}
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index 9adc50e59..906dd509c 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -84,6 +84,7 @@ class _SVG {
String get solidSliders => "assets/svg/sliders-solid.svg";
String get questionMessage => "assets/svg/message-question.svg";
String get envelope => "assets/svg/envelope.svg";
+ String get share => "assets/svg/share-2.svg";
String get receive => "assets/svg/tx-icon-receive.svg";
String get receivePending => "assets/svg/tx-icon-receive-pending.svg";
diff --git a/pubspec.yaml b/pubspec.yaml
index f2faf1497..7f8bd4507 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -255,6 +255,7 @@ flutter:
- assets/svg/sliders-solid.svg
- assets/svg/message-question.svg
- assets/svg/envelope.svg
+ - assets/svg/share-2.svg
# coin icons
- assets/svg/coin_icons/Bitcoin.svg
- assets/svg/coin_icons/Dogecoin.svg