mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-08 03:39:23 +00:00
WIP musig send view, but wallet creation not working correctly ATM
This commit is contained in:
parent
6d9c8f9356
commit
d986f27c96
5 changed files with 596 additions and 3 deletions
581
lib/pages/send_view/multisig/multisig_send_view.dart
Normal file
581
lib/pages/send_view/multisig/multisig_send_view.dart
Normal file
|
@ -0,0 +1,581 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Stack Wallet.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Cypher Stack
|
||||||
|
* All Rights Reserved.
|
||||||
|
* The code is distributed under GPLv3 license, see LICENSE file for details.
|
||||||
|
* Generated by Cypher Stack on 2023-05-26
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
|
import '../../../frost_route_generator.dart';
|
||||||
|
import '../../../models/isar/models/isar_models.dart';
|
||||||
|
import '../../../providers/frost_wallet/frost_wallet_providers.dart';
|
||||||
|
import '../../../providers/providers.dart';
|
||||||
|
import '../../../providers/wallet/public_private_balance_state_provider.dart';
|
||||||
|
import '../../../themes/coin_icon_provider.dart';
|
||||||
|
import '../../../themes/stack_colors.dart';
|
||||||
|
import '../../../utilities/amount/amount.dart';
|
||||||
|
import '../../../utilities/amount/amount_formatter.dart';
|
||||||
|
import '../../../utilities/constants.dart';
|
||||||
|
import '../../../utilities/show_loading.dart';
|
||||||
|
import '../../../utilities/text_styles.dart';
|
||||||
|
import '../../../utilities/util.dart';
|
||||||
|
import '../../../wallets/crypto_currency/crypto_currency.dart';
|
||||||
|
import '../../../wallets/isar/providers/wallet_info_provider.dart';
|
||||||
|
import '../../../wallets/models/tx_data.dart';
|
||||||
|
import '../../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
|
||||||
|
import '../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart';
|
||||||
|
import '../../../widgets/background.dart';
|
||||||
|
import '../../../widgets/conditional_parent.dart';
|
||||||
|
import '../../../widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import '../../../widgets/custom_buttons/blue_text_button.dart';
|
||||||
|
import '../../../widgets/desktop/primary_button.dart';
|
||||||
|
import '../../../widgets/desktop/secondary_button.dart';
|
||||||
|
import '../../../widgets/fee_slider.dart';
|
||||||
|
import '../../../widgets/frost_scaffold.dart';
|
||||||
|
import '../../../widgets/icon_widgets/x_icon.dart';
|
||||||
|
import '../../../widgets/rounded_white_container.dart';
|
||||||
|
import '../../../widgets/stack_dialog.dart';
|
||||||
|
import '../../../widgets/stack_text_field.dart';
|
||||||
|
import '../../../widgets/textfield_icon_button.dart';
|
||||||
|
import '../../coin_control/coin_control_view.dart';
|
||||||
|
import 'recipient.dart';
|
||||||
|
|
||||||
|
class MultisigSendView extends ConsumerStatefulWidget {
|
||||||
|
const MultisigSendView({
|
||||||
|
super.key,
|
||||||
|
required this.walletId,
|
||||||
|
required this.coin,
|
||||||
|
});
|
||||||
|
|
||||||
|
static const String routeName = "/frostSendView";
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final CryptoCurrency coin;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<MultisigSendView> createState() => _MultisigSendViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MultisigSendViewState extends ConsumerState<MultisigSendView> {
|
||||||
|
final List<int> recipientWidgetIndexes = [0];
|
||||||
|
int _greatestWidgetIndex = 0;
|
||||||
|
|
||||||
|
late final String walletId;
|
||||||
|
late final CryptoCurrency coin;
|
||||||
|
|
||||||
|
late TextEditingController noteController;
|
||||||
|
late TextEditingController onChainNoteController;
|
||||||
|
|
||||||
|
final _noteFocusNode = FocusNode();
|
||||||
|
|
||||||
|
Set<UTXO> selectedUTXOs = {};
|
||||||
|
|
||||||
|
bool _createSignLock = false;
|
||||||
|
|
||||||
|
Future<TxData> _loadingFuture() async {
|
||||||
|
final wallet = ref.read(pWallets).getWallet(walletId) as BitcoinFrostWallet;
|
||||||
|
|
||||||
|
final recipients = recipientWidgetIndexes
|
||||||
|
.map((i) => ref.read(pRecipient(i).state).state)
|
||||||
|
.map((e) => (address: e!.address, amount: e!.amount!, isChange: false))
|
||||||
|
.toList(growable: false);
|
||||||
|
|
||||||
|
final txData = await wallet.frostCreateSignConfig(
|
||||||
|
txData: TxData(recipients: recipients),
|
||||||
|
feePerWeight: customFeeRate,
|
||||||
|
);
|
||||||
|
|
||||||
|
return txData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _createSignConfig() async {
|
||||||
|
if (_createSignLock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_createSignLock = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// wait for keyboard to disappear
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
await Future<void>.delayed(
|
||||||
|
const Duration(milliseconds: 100),
|
||||||
|
);
|
||||||
|
|
||||||
|
TxData? txData;
|
||||||
|
if (mounted) {
|
||||||
|
txData = await showLoading<TxData>(
|
||||||
|
whileFuture: _loadingFuture(),
|
||||||
|
context: context,
|
||||||
|
message: "Generating sign config",
|
||||||
|
rootNavigator: Util.isDesktop,
|
||||||
|
onException: (e) {
|
||||||
|
throw e;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final wallet =
|
||||||
|
ref.read(pWallets).getWallet(walletId) as BitcoinFrostWallet;
|
||||||
|
|
||||||
|
if (mounted && txData != null) {
|
||||||
|
ref.read(pFrostTxData.notifier).state = txData;
|
||||||
|
|
||||||
|
ref.read(pFrostScaffoldArgs.state).state = (
|
||||||
|
info: (
|
||||||
|
walletName: wallet.info.name,
|
||||||
|
frostCurrency: wallet.cryptoCurrency,
|
||||||
|
),
|
||||||
|
walletId: walletId,
|
||||||
|
stepRoutes: FrostRouteGenerator.sendFrostTxStepRoutes,
|
||||||
|
parentNav: Navigator.of(context),
|
||||||
|
frostInterruptionDialogType:
|
||||||
|
FrostInterruptionDialogType.transactionCreation,
|
||||||
|
callerRouteName: MultisigSendView.routeName,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Navigator.of(context).pushNamed(
|
||||||
|
FrostStepScaffold.routeName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (mounted) {
|
||||||
|
unawaited(
|
||||||
|
showDialog<dynamic>(
|
||||||
|
context: context,
|
||||||
|
useSafeArea: false,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (context) {
|
||||||
|
return StackDialog(
|
||||||
|
title: "Create sign config failed",
|
||||||
|
message: e.toString(),
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_createSignLock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int customFeeRate = 1;
|
||||||
|
|
||||||
|
bool _buttonEnabled = false;
|
||||||
|
|
||||||
|
bool _validateRecipientFormStatesHelper() {
|
||||||
|
for (final i in recipientWidgetIndexes) {
|
||||||
|
final state = ref.read(pRecipient(i));
|
||||||
|
if (state?.amount == null ||
|
||||||
|
state?.address == null ||
|
||||||
|
state!.address.isEmpty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _validateRecipientFormStates() {
|
||||||
|
setState(() {
|
||||||
|
_buttonEnabled = _validateRecipientFormStatesHelper();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
coin = widget.coin;
|
||||||
|
walletId = widget.walletId;
|
||||||
|
|
||||||
|
noteController = TextEditingController();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
noteController.dispose();
|
||||||
|
|
||||||
|
_noteFocusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
debugPrint("BUILD: $runtimeType");
|
||||||
|
final wallet = ref.watch(pWallets).getWallet(walletId);
|
||||||
|
|
||||||
|
final showCoinControl = wallet is CoinControlInterface &&
|
||||||
|
ref.watch(
|
||||||
|
prefsChangeNotifierProvider.select(
|
||||||
|
(value) => value.enableCoinControl,
|
||||||
|
),
|
||||||
|
) &&
|
||||||
|
(coin is Firo
|
||||||
|
? ref.watch(publicPrivateBalanceStateProvider) == FiroType.public
|
||||||
|
: true);
|
||||||
|
|
||||||
|
return ConditionalParent(
|
||||||
|
condition: !Util.isDesktop,
|
||||||
|
builder: (child) => Background(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: AppBarBackButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (FocusScope.of(context).hasFocus) {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||||
|
}
|
||||||
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
"Sends ${coin.ticker}",
|
||||||
|
style: STextStyles.navBarTitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: LayoutBuilder(
|
||||||
|
builder: (builderContext, constraints) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
// subtract top and bottom padding set in parent
|
||||||
|
minHeight: constraints.maxHeight,
|
||||||
|
),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: Util.isDesktop,
|
||||||
|
builder: (child) => Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
vertical: 14,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
if (!Util.isDesktop)
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.file(
|
||||||
|
File(
|
||||||
|
ref.watch(
|
||||||
|
coinIconProvider(coin),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 6,
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
ref.watch(pWalletName(walletId)),
|
||||||
|
style: STextStyles.titleBold12(context)
|
||||||
|
.copyWith(fontSize: 14),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
// const SizedBox(
|
||||||
|
// height: 2,
|
||||||
|
// ),
|
||||||
|
Text(
|
||||||
|
"Available balance",
|
||||||
|
style: STextStyles.label(context)
|
||||||
|
.copyWith(fontSize: 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Util.isDesktop
|
||||||
|
? const SizedBox(
|
||||||
|
height: 24,
|
||||||
|
)
|
||||||
|
: const Spacer(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
ref.watch(pAmountFormatter(coin)).format(
|
||||||
|
ref
|
||||||
|
.watch(pWalletBalance(walletId))
|
||||||
|
.spendable,
|
||||||
|
),
|
||||||
|
style:
|
||||||
|
STextStyles.titleBold12(context).copyWith(
|
||||||
|
fontSize: 10,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: recipientWidgetIndexes.length > 1 ? 8 : 16,
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
for (int i = 0; i < recipientWidgetIndexes.length; i++)
|
||||||
|
ConditionalParent(
|
||||||
|
condition: recipientWidgetIndexes.length > 1,
|
||||||
|
builder: (child) => Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
child: Recipient(
|
||||||
|
key: Key(
|
||||||
|
"recipientKey_${recipientWidgetIndexes[i]}",
|
||||||
|
),
|
||||||
|
index: recipientWidgetIndexes[i],
|
||||||
|
displayNumber: i + 1,
|
||||||
|
coin: coin,
|
||||||
|
onChanged: () {
|
||||||
|
_validateRecipientFormStates();
|
||||||
|
},
|
||||||
|
remove: i == 0 && recipientWidgetIndexes.length == 1
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
ref
|
||||||
|
.read(
|
||||||
|
pRecipient(recipientWidgetIndexes[i])
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
|
.state = null;
|
||||||
|
recipientWidgetIndexes.removeAt(i);
|
||||||
|
setState(() {});
|
||||||
|
_validateRecipientFormStates();
|
||||||
|
},
|
||||||
|
addAnotherRecipientTapped: () {
|
||||||
|
// used for tracking recipient forms
|
||||||
|
_greatestWidgetIndex++;
|
||||||
|
recipientWidgetIndexes.add(_greatestWidgetIndex);
|
||||||
|
setState(() {});
|
||||||
|
_validateRecipientFormStates();
|
||||||
|
},
|
||||||
|
sendAllTapped: () {
|
||||||
|
return ref.read(pAmountFormatter(coin)).format(
|
||||||
|
ref.read(pWalletBalance(walletId)).spendable,
|
||||||
|
withUnitName: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (recipientWidgetIndexes.length > 1)
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
if (recipientWidgetIndexes.length > 1)
|
||||||
|
SecondaryButton(
|
||||||
|
width: double.infinity,
|
||||||
|
label: "Add recipient",
|
||||||
|
onPressed: () {
|
||||||
|
// used for tracking recipient forms
|
||||||
|
_greatestWidgetIndex++;
|
||||||
|
recipientWidgetIndexes.add(_greatestWidgetIndex);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (showCoinControl)
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
if (showCoinControl)
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Coin control",
|
||||||
|
style: STextStyles.w500_14(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CustomTextButton(
|
||||||
|
text: selectedUTXOs.isEmpty
|
||||||
|
? "Select coins"
|
||||||
|
: "Selected coins (${selectedUTXOs.length})",
|
||||||
|
onTap: () async {
|
||||||
|
if (FocusScope.of(context).hasFocus) {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
await Future<void>.delayed(
|
||||||
|
const Duration(milliseconds: 100),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
// TODO: [prio=high] make sure this coincontrol works correctly
|
||||||
|
|
||||||
|
Amount? amount;
|
||||||
|
|
||||||
|
final result = await Navigator.of(context).pushNamed(
|
||||||
|
CoinControlView.routeName,
|
||||||
|
arguments: Tuple4(
|
||||||
|
walletId,
|
||||||
|
CoinControlViewType.use,
|
||||||
|
amount,
|
||||||
|
selectedUTXOs,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result is Set<UTXO>) {
|
||||||
|
setState(() {
|
||||||
|
selectedUTXOs = result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Note (optional)",
|
||||||
|
style: STextStyles.smallMed12(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
autocorrect: Util.isDesktop ? false : true,
|
||||||
|
enableSuggestions: Util.isDesktop ? false : true,
|
||||||
|
controller: noteController,
|
||||||
|
focusNode: _noteFocusNode,
|
||||||
|
style: STextStyles.field(context),
|
||||||
|
onChanged: (_) => setState(() {}),
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Type something...",
|
||||||
|
_noteFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
suffixIcon: noteController.text.isNotEmpty
|
||||||
|
? Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 0),
|
||||||
|
child: UnconstrainedBox(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
TextFieldIconButton(
|
||||||
|
child: const XIcon(),
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
noteController.text = "";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 12,
|
||||||
|
top: 16,
|
||||||
|
),
|
||||||
|
child: FeeSlider(
|
||||||
|
coin: coin,
|
||||||
|
showWU: true,
|
||||||
|
onSatVByteChanged: (rate) {
|
||||||
|
customFeeRate = rate;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Util.isDesktop
|
||||||
|
? const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
)
|
||||||
|
: const Spacer(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
PrimaryButton(
|
||||||
|
label: "Create multisig transaction",
|
||||||
|
enabled: _buttonEnabled,
|
||||||
|
onPressed: _createSignConfig,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -484,8 +484,10 @@ class _MultisigSetupViewState extends ConsumerState<MultisigCoordinatorView> {
|
||||||
'cosignerXpubs': xpubControllers.map((e) => e.text).toList(),
|
'cosignerXpubs': xpubControllers.map((e) => e.text).toList(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final newCoin = BIP48Bitcoin(parentWallet.cryptoCurrency.network);
|
||||||
|
|
||||||
final info = WalletInfo.createNew(
|
final info = WalletInfo.createNew(
|
||||||
coin: BIP48Bitcoin(parentWallet.cryptoCurrency.network),
|
coin: newCoin,
|
||||||
name:
|
name:
|
||||||
'widget.walletName', // TODO [prio=high]: Add wallet name input field to multisig setup view and pass it to the coordinator view here.
|
'widget.walletName', // TODO [prio=high]: Add wallet name input field to multisig setup view and pass it to the coordinator view here.
|
||||||
restoreHeight: await parentWallet.chainHeight,
|
restoreHeight: await parentWallet.chainHeight,
|
||||||
|
@ -524,7 +526,7 @@ class _MultisigSetupViewState extends ConsumerState<MultisigCoordinatorView> {
|
||||||
node ??= parentWallet.cryptoCurrency.defaultNode;
|
node ??= parentWallet.cryptoCurrency.defaultNode;
|
||||||
await ref
|
await ref
|
||||||
.read(nodeServiceChangeNotifierProvider)
|
.read(nodeServiceChangeNotifierProvider)
|
||||||
.setPrimaryNodeFor(coin: parentWallet.cryptoCurrency, node: node);
|
.setPrimaryNodeFor(coin: newCoin, node: node);
|
||||||
|
|
||||||
final txTracker = TransactionNotificationTracker(walletId: info.walletId);
|
final txTracker = TransactionNotificationTracker(walletId: info.walletId);
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,12 @@ import '../../utilities/enums/sync_type_enum.dart';
|
||||||
import '../../utilities/logger.dart';
|
import '../../utilities/logger.dart';
|
||||||
import '../../utilities/show_loading.dart';
|
import '../../utilities/show_loading.dart';
|
||||||
import '../../utilities/text_styles.dart';
|
import '../../utilities/text_styles.dart';
|
||||||
|
import '../../wallets/crypto_currency/coins/bip48_bitcoin.dart';
|
||||||
import '../../wallets/crypto_currency/crypto_currency.dart';
|
import '../../wallets/crypto_currency/crypto_currency.dart';
|
||||||
import '../../wallets/crypto_currency/interfaces/bip48_currency_interface.dart';
|
import '../../wallets/crypto_currency/interfaces/bip48_currency_interface.dart';
|
||||||
import '../../wallets/crypto_currency/intermediate/frost_currency.dart';
|
import '../../wallets/crypto_currency/intermediate/frost_currency.dart';
|
||||||
import '../../wallets/isar/providers/wallet_info_provider.dart';
|
import '../../wallets/isar/providers/wallet_info_provider.dart';
|
||||||
|
import '../../wallets/wallet/impl/bip48_bitcoin_wallet.dart';
|
||||||
import '../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
|
import '../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
|
||||||
import '../../wallets/wallet/impl/firo_wallet.dart';
|
import '../../wallets/wallet/impl/firo_wallet.dart';
|
||||||
import '../../wallets/wallet/intermediate/lib_monero_wallet.dart';
|
import '../../wallets/wallet/intermediate/lib_monero_wallet.dart';
|
||||||
|
@ -93,6 +95,7 @@ import '../paynym/paynym_claim_view.dart';
|
||||||
import '../paynym/paynym_home_view.dart';
|
import '../paynym/paynym_home_view.dart';
|
||||||
import '../receive_view/receive_view.dart';
|
import '../receive_view/receive_view.dart';
|
||||||
import '../send_view/frost_ms/frost_send_view.dart';
|
import '../send_view/frost_ms/frost_send_view.dart';
|
||||||
|
import '../send_view/multisig/multisig_send_view.dart';
|
||||||
import '../send_view/send_view.dart';
|
import '../send_view/send_view.dart';
|
||||||
import '../settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart';
|
import '../settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart';
|
||||||
import '../settings_views/wallet_settings_view/wallet_settings_view.dart';
|
import '../settings_views/wallet_settings_view/wallet_settings_view.dart';
|
||||||
|
@ -1057,7 +1060,9 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
wallet is BitcoinFrostWallet
|
wallet is BitcoinFrostWallet
|
||||||
? FrostSendView.routeName
|
? FrostSendView.routeName
|
||||||
: SendView.routeName,
|
: wallet is BIP48BitcoinWallet
|
||||||
|
? MultisigSendView.routeName
|
||||||
|
: SendView.routeName,
|
||||||
arguments: (
|
arguments: (
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
coin: coin,
|
coin: coin,
|
||||||
|
|
|
@ -22,10 +22,12 @@ import '../../utilities/flutter_secure_storage_interface.dart';
|
||||||
import '../../utilities/logger.dart';
|
import '../../utilities/logger.dart';
|
||||||
import '../../utilities/paynym_is_api.dart';
|
import '../../utilities/paynym_is_api.dart';
|
||||||
import '../../utilities/prefs.dart';
|
import '../../utilities/prefs.dart';
|
||||||
|
import '../crypto_currency/coins/bip48_bitcoin.dart';
|
||||||
import '../crypto_currency/crypto_currency.dart';
|
import '../crypto_currency/crypto_currency.dart';
|
||||||
import '../isar/models/wallet_info.dart';
|
import '../isar/models/wallet_info.dart';
|
||||||
import '../models/tx_data.dart';
|
import '../models/tx_data.dart';
|
||||||
import 'impl/banano_wallet.dart';
|
import 'impl/banano_wallet.dart';
|
||||||
|
import 'impl/bip48_bitcoin_wallet.dart';
|
||||||
import 'impl/bitcoin_frost_wallet.dart';
|
import 'impl/bitcoin_frost_wallet.dart';
|
||||||
import 'impl/bitcoin_wallet.dart';
|
import 'impl/bitcoin_wallet.dart';
|
||||||
import 'impl/bitcoincash_wallet.dart';
|
import 'impl/bitcoincash_wallet.dart';
|
||||||
|
@ -335,6 +337,9 @@ abstract class Wallet<T extends CryptoCurrency> {
|
||||||
case const (Banano):
|
case const (Banano):
|
||||||
return BananoWallet(net);
|
return BananoWallet(net);
|
||||||
|
|
||||||
|
case const (BIP48Bitcoin):
|
||||||
|
return BIP48BitcoinWallet(net);
|
||||||
|
|
||||||
case const (Bitcoin):
|
case const (Bitcoin):
|
||||||
return BitcoinWallet(net);
|
return BitcoinWallet(net);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue