mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-06 18:59:24 +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(),
|
||||
});
|
||||
|
||||
final newCoin = BIP48Bitcoin(parentWallet.cryptoCurrency.network);
|
||||
|
||||
final info = WalletInfo.createNew(
|
||||
coin: BIP48Bitcoin(parentWallet.cryptoCurrency.network),
|
||||
coin: newCoin,
|
||||
name:
|
||||
'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,
|
||||
|
@ -524,7 +526,7 @@ class _MultisigSetupViewState extends ConsumerState<MultisigCoordinatorView> {
|
|||
node ??= parentWallet.cryptoCurrency.defaultNode;
|
||||
await ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.setPrimaryNodeFor(coin: parentWallet.cryptoCurrency, node: node);
|
||||
.setPrimaryNodeFor(coin: newCoin, node: node);
|
||||
|
||||
final txTracker = TransactionNotificationTracker(walletId: info.walletId);
|
||||
|
||||
|
|
|
@ -45,10 +45,12 @@ import '../../utilities/enums/sync_type_enum.dart';
|
|||
import '../../utilities/logger.dart';
|
||||
import '../../utilities/show_loading.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/interfaces/bip48_currency_interface.dart';
|
||||
import '../../wallets/crypto_currency/intermediate/frost_currency.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/firo_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 '../receive_view/receive_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 '../settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_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(
|
||||
wallet is BitcoinFrostWallet
|
||||
? FrostSendView.routeName
|
||||
: SendView.routeName,
|
||||
: wallet is BIP48BitcoinWallet
|
||||
? MultisigSendView.routeName
|
||||
: SendView.routeName,
|
||||
arguments: (
|
||||
walletId: walletId,
|
||||
coin: coin,
|
||||
|
|
|
@ -22,10 +22,12 @@ import '../../utilities/flutter_secure_storage_interface.dart';
|
|||
import '../../utilities/logger.dart';
|
||||
import '../../utilities/paynym_is_api.dart';
|
||||
import '../../utilities/prefs.dart';
|
||||
import '../crypto_currency/coins/bip48_bitcoin.dart';
|
||||
import '../crypto_currency/crypto_currency.dart';
|
||||
import '../isar/models/wallet_info.dart';
|
||||
import '../models/tx_data.dart';
|
||||
import 'impl/banano_wallet.dart';
|
||||
import 'impl/bip48_bitcoin_wallet.dart';
|
||||
import 'impl/bitcoin_frost_wallet.dart';
|
||||
import 'impl/bitcoin_wallet.dart';
|
||||
import 'impl/bitcoincash_wallet.dart';
|
||||
|
@ -335,6 +337,9 @@ abstract class Wallet<T extends CryptoCurrency> {
|
|||
case const (Banano):
|
||||
return BananoWallet(net);
|
||||
|
||||
case const (BIP48Bitcoin):
|
||||
return BIP48BitcoinWallet(net);
|
||||
|
||||
case const (Bitcoin):
|
||||
return BitcoinWallet(net);
|
||||
|
||||
|
|
Loading…
Reference in a new issue