diff --git a/cw_lightning/lib/lightning_receive_page_option.dart b/cw_lightning/lib/lightning_receive_page_option.dart new file mode 100644 index 000000000..fd2917a14 --- /dev/null +++ b/cw_lightning/lib/lightning_receive_page_option.dart @@ -0,0 +1,19 @@ +import 'package:cw_core/receive_page_option.dart'; + +class LightningReceivePageOption implements ReceivePageOption { + static const lightningOnchain = LightningReceivePageOption._('lightningOnchain'); + static const lightningInvoice = LightningReceivePageOption._('lightningInvoice'); + + const LightningReceivePageOption._(this.value); + + final String value; + + String toString() { + return value; + } + + static const all = [ + LightningReceivePageOption.lightningInvoice, + LightningReceivePageOption.lightningOnchain + ]; +} diff --git a/cw_lightning/lib/lightning_wallet.dart b/cw_lightning/lib/lightning_wallet.dart index 36d6650e0..2629dbdd2 100644 --- a/cw_lightning/lib/lightning_wallet.dart +++ b/cw_lightning/lib/lightning_wallet.dart @@ -1,12 +1,15 @@ import 'dart:convert'; import 'dart:io'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:breez_sdk/breez_sdk.dart'; import 'package:breez_sdk/bridge_generated.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; +import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/pathForWallet.dart'; @@ -24,8 +27,6 @@ import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; -import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart'; @@ -54,6 +55,7 @@ abstract class LightningWalletBase late ElectrumWalletAddresses walletAddresses; bitcoin.NetworkType networkType = bitcoin.bitcoin; + late BasedUtxoNetwork network; @override BitcoinWalletKeys get keys => @@ -63,18 +65,20 @@ abstract class LightningWalletBase @observable SyncStatus syncStatus; - LightningWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - ElectrumClient? electrumClient, - List? initialAddresses, - LightningBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : hd = bitcoin.HDWallet.fromSeed(seedBytes, network: bitcoin.bitcoin).derivePath("m/0'/0"), + LightningWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + ElectrumClient? electrumClient, + BasedUtxoNetwork? networkParam, + List? initialAddresses, + LightningBalance? initialBalance, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) : hd = bitcoin.HDWallet.fromSeed(seedBytes, network: bitcoin.bitcoin).derivePath("m/0'/0"), syncStatus = NotConnectedSyncStatus(), mnemonic = mnemonic, _password = password, @@ -85,14 +89,24 @@ abstract class LightningWalletBase }), super(walletInfo) { transactionHistory = LightningTransactionHistory(walletInfo: walletInfo, password: password); - walletAddresses = BitcoinWalletAddresses(walletInfo, - electrumClient: electrumClient ?? ElectrumClient(), - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), - networkType: networkType); + + this.network = networkType == bitcoin.bitcoin + ? BitcoinNetwork.mainnet + : networkType == litecoinNetwork + ? LitecoinNetwork.mainnet + : BitcoinNetwork.testnet; + this.isTestnet = networkType == bitcoin.testnet; + + walletAddresses = BitcoinWalletAddresses( + walletInfo, + electrumClient: electrumClient ?? ElectrumClient(), + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + network: networkParam ?? network, + ); this.electrumClient = electrumClient ?? ElectrumClient(); @@ -108,23 +122,26 @@ abstract class LightningWalletBase }); } - static Future create( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) async { + static Future create({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + BasedUtxoNetwork? network, + List? initialAddresses, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) async { return LightningWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - seedBytes: await mnemonicToSeedBytes(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + seedBytes: await mnemonicToSeedBytes(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + ); } static Future open({ @@ -133,16 +150,22 @@ abstract class LightningWalletBase required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, + walletInfo.network != null ? BasedUtxoNetwork.fromName(walletInfo.network!) : null); + return LightningWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + // initialBalance: snp.balance, + seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + networkParam: snp.network, + ); } Future setupBreez(Uint8List seedBytes) async { @@ -312,10 +335,14 @@ abstract class LightningWalletBase String toJSON() => json.encode({ 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'balance': balance[currency]?.toJSON() + 'account_index': walletAddresses.currentReceiveAddressIndexByType, + 'change_address_index': walletAddresses.currentChangeAddressIndexByType, + 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(), + 'address_page_type': walletInfo.addressPageType == null + ? SegwitAddresType.p2wpkh.toString() + : walletInfo.addressPageType.toString(), + 'balance': balance[currency]?.toJSON(), + 'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet', }); @override diff --git a/cw_lightning/lib/lightning_wallet_service.dart b/cw_lightning/lib/lightning_wallet_service.dart index 9a46413dc..f8f6abab2 100644 --- a/cw_lightning/lib/lightning_wallet_service.dart +++ b/cw_lightning/lib/lightning_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; @@ -96,16 +97,22 @@ class LightningWalletService extends WalletService restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } + final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet; + credentials.walletInfo?.network = network.value; + final wallet = await LightningWalletBase.create( - password: credentials.password!, - mnemonic: credentials.mnemonic, - walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource, + network: network, + ); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_solana/lib/solana_wallet_service.dart b/cw_solana/lib/solana_wallet_service.dart index 8abf1ffbb..b3ff22e7e 100644 --- a/cw_solana/lib/solana_wallet_service.dart +++ b/cw_solana/lib/solana_wallet_service.dart @@ -19,7 +19,7 @@ class SolanaWalletService extends WalletService walletInfoSource; @override - Future create(SolanaNewWalletCredentials credentials) async { + Future create(SolanaNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -67,7 +67,8 @@ class SolanaWalletService extends WalletService restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials, + {bool? isTestnet}) async { final wallet = SolanaWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -82,7 +83,8 @@ class SolanaWalletService extends WalletService restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw SolanaMnemonicIsIncorrectException(); } diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index e29bc7393..59fdb1ba5 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:cw_lightning/lightning_receive_page_option.dart'; import 'package:flutter/material.dart'; class MainActions { @@ -60,7 +61,7 @@ class MainActions { Navigator.pushNamed( context, Routes.lightningInvoice, - arguments: [ReceivePageOption.lightningInvoice], + arguments: [LightningReceivePageOption.lightningInvoice], ); return; } diff --git a/lib/entities/receive_page_option.dart b/lib/entities/receive_page_option.dart deleted file mode 100644 index 573f4924b..000000000 --- a/lib/entities/receive_page_option.dart +++ /dev/null @@ -1,30 +0,0 @@ -enum ReceivePageOption { - mainnet, - anonPayInvoice, - anonPayDonationLink, - lightningInvoice, - lightningOnchain; - - @override - String toString() { - String label = ''; - switch (this) { - case ReceivePageOption.mainnet: - label = 'Mainnet'; - break; - case ReceivePageOption.anonPayInvoice: - label = 'Trocador AnonPay Invoice'; - break; - case ReceivePageOption.anonPayDonationLink: - label = 'Trocador AnonPay Donation Link'; - break; - case ReceivePageOption.lightningInvoice: - label = 'Lightning via Invoice'; - break; - case ReceivePageOption.lightningOnchain: - label = 'Lightning via BTC address'; - break; - } - return label; - } -} diff --git a/lib/lightning/cw_lightning.dart b/lib/lightning/cw_lightning.dart index 32b11463e..c2cb983cc 100644 --- a/lib/lightning/cw_lightning.dart +++ b/lib/lightning/cw_lightning.dart @@ -91,28 +91,28 @@ class CWLightning extends Lightning { priority: priority != null ? priority as BitcoinTransactionPriority : null, feeRate: feeRate); - @override - List getAddresses(Object wallet) { - final lightningWallet = wallet as ElectrumWallet; - return lightningWallet.walletAddresses.addresses - .map((BitcoinAddressRecord addr) => addr.address) - .toList(); - } + @override + List getAddresses(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.addressesByReceiveType + .map((BitcoinAddressRecord addr) => addr.address) + .toList(); + } - @override - @computed - List getSubAddresses(Object wallet) { - final electrumWallet = wallet as ElectrumWallet; - return electrumWallet.walletAddresses.addresses - .map((BitcoinAddressRecord addr) => ElectrumSubAddress( - id: addr.index, - name: addr.name, - address: addr.address, - txCount: addr.txCount, - balance: addr.balance, - isChange: addr.isHidden)) - .toList(); - } + @override + @computed + List getSubAddresses(Object wallet) { + final electrumWallet = wallet as ElectrumWallet; + return electrumWallet.walletAddresses.addressesByReceiveType + .map((BitcoinAddressRecord addr) => ElectrumSubAddress( + id: addr.index, + name: addr.name, + address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, + txCount: addr.txCount, + balance: addr.balance, + isChange: addr.isHidden)) + .toList(); + } @override String getAddress(Object wallet) { @@ -158,4 +158,7 @@ class CWLightning extends Lightning { @override TransactionPriority getLightningTransactionPrioritySlow() => BitcoinTransactionPriority.slow; + + @override + List getLightningReceivePageOptions() => LightningReceivePageOption.all; } \ No newline at end of file diff --git a/lib/lightning/lightning.dart b/lib/lightning/lightning.dart index 8ef4853e4..d2f31296d 100644 --- a/lib/lightning/lightning.dart +++ b/lib/lightning/lightning.dart @@ -7,6 +7,7 @@ import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -19,6 +20,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_lightning/lightning_wallet_service.dart'; +import 'package:cw_lightning/lightning_receive_page_option.dart'; part 'cw_lightning.dart'; @@ -64,5 +66,6 @@ abstract class Lightning { Box walletInfoSource, Box unspentCoinSource); TransactionPriority getLightningTransactionPriorityMedium(); TransactionPriority getLightningTransactionPrioritySlow(); + List getLightningReceivePageOptions(); } \ No newline at end of file diff --git a/lib/src/screens/receive/lightning_invoice_page.dart b/lib/src/screens/receive/lightning_invoice_page.dart index a961646b2..fbf213d4a 100644 --- a/lib/src/screens/receive/lightning_invoice_page.dart +++ b/lib/src/screens/receive/lightning_invoice_page.dart @@ -3,22 +3,18 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; -import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/di.dart'; -import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; -import 'package:cake_wallet/src/screens/receive/widgets/anonpay_input_form.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; -import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/lightning_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/lightning_view_model.dart'; +import 'package:cw_core/receive_page_option.dart'; +import 'package:cw_lightning/lightning_receive_page_option.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -30,7 +26,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:mobx/mobx.dart'; -import 'package:shared_preferences/shared_preferences.dart'; class LightningInvoicePage extends BasePage { LightningInvoicePage({ @@ -219,13 +214,13 @@ class LightningInvoicePage extends BasePage { reaction((_) => receiveOptionViewModel.selectedReceiveOption, (ReceivePageOption option) async { switch (option) { - case ReceivePageOption.lightningInvoice: + case LightningReceivePageOption.lightningInvoice: break; - case ReceivePageOption.lightningOnchain: + case LightningReceivePageOption.lightningOnchain: Navigator.popAndPushNamed( context, Routes.lightningReceiveOnchain, - arguments: [ReceivePageOption.lightningOnchain], + arguments: [LightningReceivePageOption.lightningOnchain], ); break; default: diff --git a/lib/src/screens/receive/lightning_receive_page.dart b/lib/src/screens/receive/lightning_receive_page.dart index 7348dfbfe..205ff9f6b 100644 --- a/lib/src/screens/receive/lightning_receive_page.dart +++ b/lib/src/screens/receive/lightning_receive_page.dart @@ -1,5 +1,4 @@ import 'package:cake_wallet/entities/qr_view_data.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; @@ -10,6 +9,7 @@ import 'package:cake_wallet/utils/brightness_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/lightning_view_model.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; diff --git a/lib/view_model/dashboard/receive_option_view_model.dart b/lib/view_model/dashboard/receive_option_view_model.dart index 09c5ba078..cf628c4c5 100644 --- a/lib/view_model/dashboard/receive_option_view_model.dart +++ b/lib/view_model/dashboard/receive_option_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/lightning/lightning.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; @@ -22,7 +23,7 @@ abstract class ReceiveOptionViewModelBase with Store { _options = [ReceivePageOption.mainnet]; break; case WalletType.lightning: - _options = [ReceivePageOption.lightningInvoice, ReceivePageOption.lightningOnchain]; + _options = [...lightning!.getLightningReceivePageOptions()]; break; case WalletType.bitcoin: _options = [ diff --git a/tool/configure.dart b/tool/configure.dart index ad0f309aa..7fad144b6 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -726,6 +726,7 @@ import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; """; @@ -739,6 +740,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_lightning/lightning_wallet_service.dart'; +import 'package:cw_lightning/lightning_receive_page_option.dart'; """; const lightningCwPart = "part 'cw_lightning.dart';"; const lightningContent = """